react-bkoi-gl 1.0.7 → 2.0.1
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.
- package/LICENSE +21 -0
- package/README.md +172 -18
- package/dist/index.cjs +671 -736
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +370 -0
- package/dist/index.d.ts +370 -2
- package/dist/index.js +1434 -2
- package/dist/index.js.map +1 -1
- package/dist/styles/index.d.ts +4 -0
- package/dist/styles/react-bkoi-gl.css +1 -1
- package/package.json +84 -36
- package/bkoi-gl/package.json +0 -6
- package/dist/components/attribution-control.d.ts +0 -11
- package/dist/components/attribution-control.js +0 -19
- package/dist/components/attribution-control.js.map +0 -1
- package/dist/components/fullscreen-control.d.ts +0 -14
- package/dist/components/fullscreen-control.js +0 -21
- package/dist/components/fullscreen-control.js.map +0 -1
- package/dist/components/geolocate-control.d.ts +0 -37
- package/dist/components/geolocate-control.js +0 -46
- package/dist/components/geolocate-control.js.map +0 -1
- package/dist/components/layer.d.ts +0 -17
- package/dist/components/layer.js +0 -99
- package/dist/components/layer.js.map +0 -1
- package/dist/components/map.d.ts +0 -23
- package/dist/components/map.js +0 -102
- package/dist/components/map.js.map +0 -1
- package/dist/components/marker.d.ts +0 -41
- package/dist/components/marker.js +0 -98
- package/dist/components/marker.js.map +0 -1
- package/dist/components/navigation-control.d.ts +0 -11
- package/dist/components/navigation-control.js +0 -19
- package/dist/components/navigation-control.js.map +0 -1
- package/dist/components/popup.d.ts +0 -33
- package/dist/components/popup.js +0 -79
- package/dist/components/popup.js.map +0 -1
- package/dist/components/scale-control.d.ts +0 -13
- package/dist/components/scale-control.js +0 -31
- package/dist/components/scale-control.js.map +0 -1
- package/dist/components/source.d.ts +0 -7
- package/dist/components/source.js +0 -97
- package/dist/components/source.js.map +0 -1
- package/dist/components/use-control.d.ts +0 -9
- package/dist/components/use-control.js +0 -31
- package/dist/components/use-control.js.map +0 -1
- package/dist/components/use-map.d.ts +0 -20
- package/dist/components/use-map.js +0 -54
- package/dist/components/use-map.js.map +0 -1
- package/dist/exports-bkoi-gl.cjs +0 -1512
- package/dist/exports-bkoi-gl.d.ts +0 -89
- package/dist/exports-bkoi-gl.js +0 -36
- package/dist/exports-bkoi-gl.js.map +0 -1
- package/dist/exports-mapbox.d.ts +0 -139
- package/dist/exports-mapbox.js +0 -36
- package/dist/exports-mapbox.js.map +0 -1
- package/dist/mapbox/create-ref.d.ts +0 -9
- package/dist/mapbox/create-ref.js +0 -64
- package/dist/mapbox/create-ref.js.map +0 -1
- package/dist/mapbox/mapbox.d.ts +0 -81
- package/dist/mapbox/mapbox.js +0 -476
- package/dist/mapbox/mapbox.js.map +0 -1
- package/dist/types/common.d.ts +0 -78
- package/dist/types/common.js +0 -2
- package/dist/types/common.js.map +0 -1
- package/dist/types/events-bkoi-gl.d.ts +0 -49
- package/dist/types/events-bkoi-gl.js +0 -2
- package/dist/types/events-bkoi-gl.js.map +0 -1
- package/dist/types/events-mapbox.d.ts +0 -49
- package/dist/types/events-mapbox.js +0 -2
- package/dist/types/events-mapbox.js.map +0 -1
- package/dist/types/events.d.ts +0 -39
- package/dist/types/events.js +0 -2
- package/dist/types/events.js.map +0 -1
- package/dist/types/index.d.ts +0 -70
- package/dist/types/index.js +0 -5
- package/dist/types/index.js.map +0 -1
- package/dist/types/lib.d.ts +0 -224
- package/dist/types/lib.js +0 -2
- package/dist/types/lib.js.map +0 -1
- package/dist/types/public.d.ts +0 -2
- package/dist/types/public.js +0 -2
- package/dist/types/public.js.map +0 -1
- package/dist/types/style-spec-bkoi-gl.d.ts +0 -9
- package/dist/types/style-spec-bkoi-gl.js +0 -2
- package/dist/types/style-spec-bkoi-gl.js.map +0 -1
- package/dist/types/style-spec-mapbox.d.ts +0 -7
- package/dist/types/style-spec-mapbox.js +0 -2
- package/dist/types/style-spec-mapbox.js.map +0 -1
- package/dist/utils/apply-react-style.d.ts +0 -2
- package/dist/utils/apply-react-style.js +0 -16
- package/dist/utils/apply-react-style.js.map +0 -1
- package/dist/utils/assert.d.ts +0 -1
- package/dist/utils/assert.js +0 -6
- package/dist/utils/assert.js.map +0 -1
- package/dist/utils/deep-equal.d.ts +0 -15
- package/dist/utils/deep-equal.js +0 -46
- package/dist/utils/deep-equal.js.map +0 -1
- package/dist/utils/set-globals.d.ts +0 -22
- package/dist/utils/set-globals.js +0 -19
- package/dist/utils/set-globals.js.map +0 -1
- package/dist/utils/style-utils.d.ts +0 -2
- package/dist/utils/style-utils.js +0 -42
- package/dist/utils/style-utils.js.map +0 -1
- package/dist/utils/transform.d.ts +0 -26
- package/dist/utils/transform.js +0 -56
- package/dist/utils/transform.js.map +0 -1
- package/dist/utils/use-isomorphic-layout-effect.d.ts +0 -3
- package/dist/utils/use-isomorphic-layout-effect.js +0 -4
- package/dist/utils/use-isomorphic-layout-effect.js.map +0 -1
- package/src/components/attribution-control.ts +0 -32
- package/src/components/fullscreen-control.tsx +0 -37
- package/src/components/geolocate-control.ts +0 -90
- package/src/components/layer.ts +0 -133
- package/src/components/map.tsx +0 -155
- package/src/components/marker.ts +0 -137
- package/src/components/navigation-control.ts +0 -29
- package/src/components/popup.ts +0 -116
- package/src/components/scale-control.ts +0 -46
- package/src/components/source.ts +0 -158
- package/src/components/use-control.ts +0 -64
- package/src/components/use-map.tsx +0 -69
- package/src/exports-bkoi-gl.ts +0 -156
- package/src/exports-mapbox.ts +0 -159
- package/src/index.ts +0 -2
- package/src/mapbox/create-ref.ts +0 -118
- package/src/mapbox/mapbox.ts +0 -742
- package/src/types/common.ts +0 -94
- package/src/types/events-bkoi-gl.ts +0 -78
- package/src/types/events-mapbox.ts +0 -76
- package/src/types/events.ts +0 -73
- package/src/types/index.ts +0 -93
- package/src/types/lib.ts +0 -279
- package/src/types/public.ts +0 -9
- package/src/types/style-spec-bkoi-gl.ts +0 -81
- package/src/types/style-spec-mapbox.ts +0 -80
- package/src/utils/apply-react-style.ts +0 -20
- package/src/utils/assert.ts +0 -5
- package/src/utils/deep-equal.ts +0 -61
- package/src/utils/set-globals.ts +0 -57
- package/src/utils/style-utils.ts +0 -59
- package/src/utils/transform.ts +0 -86
- package/src/utils/use-isomorphic-layout-effect.ts +0 -7
package/src/components/map.tsx
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import {useState, useRef, useEffect, useContext, useMemo, useImperativeHandle} from 'react';
|
|
3
|
-
|
|
4
|
-
import {MountedMapsContext} from './use-map';
|
|
5
|
-
import Mapbox, {MapboxProps} from '../mapbox/mapbox';
|
|
6
|
-
import createRef, {MapRef} from '../mapbox/create-ref';
|
|
7
|
-
|
|
8
|
-
import type {CSSProperties} from 'react';
|
|
9
|
-
import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect';
|
|
10
|
-
import setGlobals, {GlobalSettings} from '../utils/set-globals';
|
|
11
|
-
import type {MapLib, MapInstance, MapStyle, Callbacks} from '../types';
|
|
12
|
-
|
|
13
|
-
export type MapContextValue<MapT extends MapInstance = MapInstance> = {
|
|
14
|
-
mapLib: MapLib<MapT>;
|
|
15
|
-
map: MapRef<MapT>;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const MapContext = React.createContext<MapContextValue>(null);
|
|
19
|
-
|
|
20
|
-
type MapInitOptions<MapOptions> = Omit<
|
|
21
|
-
MapOptions,
|
|
22
|
-
'style' | 'container' | 'bounds' | 'fitBoundsOptions' | 'center'
|
|
23
|
-
>;
|
|
24
|
-
|
|
25
|
-
export type MapProps<
|
|
26
|
-
MapOptions,
|
|
27
|
-
StyleT extends MapStyle,
|
|
28
|
-
CallbacksT extends Callbacks,
|
|
29
|
-
MapT extends MapInstance
|
|
30
|
-
> = MapInitOptions<MapOptions> &
|
|
31
|
-
MapboxProps<StyleT, CallbacksT> &
|
|
32
|
-
GlobalSettings & {
|
|
33
|
-
mapLib?: MapLib<MapT> | Promise<MapLib<MapT>>;
|
|
34
|
-
reuseMaps?: boolean;
|
|
35
|
-
/** Map container id */
|
|
36
|
-
id?: string;
|
|
37
|
-
/** Map container CSS style */
|
|
38
|
-
style?: CSSProperties;
|
|
39
|
-
children?: any;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export default function Map<
|
|
43
|
-
MapOptions,
|
|
44
|
-
StyleT extends MapStyle,
|
|
45
|
-
CallbacksT extends Callbacks,
|
|
46
|
-
MapT extends MapInstance
|
|
47
|
-
>(
|
|
48
|
-
props: MapProps<MapOptions, StyleT, CallbacksT, MapT>,
|
|
49
|
-
ref: React.Ref<MapRef<MapT>>,
|
|
50
|
-
defaultLib: MapLib<MapT> | Promise<MapLib<MapT>>
|
|
51
|
-
) {
|
|
52
|
-
const mountedMapsContext = useContext(MountedMapsContext);
|
|
53
|
-
const [mapInstance, setMapInstance] = useState<Mapbox<StyleT, CallbacksT, MapT>>(null);
|
|
54
|
-
const containerRef = useRef();
|
|
55
|
-
|
|
56
|
-
const {current: contextValue} = useRef<MapContextValue<MapT>>({mapLib: null, map: null});
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
const mapLib = props.mapLib;
|
|
60
|
-
let isMounted = true;
|
|
61
|
-
let mapbox: Mapbox<StyleT, CallbacksT, MapT>;
|
|
62
|
-
|
|
63
|
-
Promise.resolve(mapLib || defaultLib)
|
|
64
|
-
.then((module: MapLib<MapT> | {default: MapLib<MapT>}) => {
|
|
65
|
-
if (!isMounted) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (!module) {
|
|
69
|
-
throw new Error('Invalid mapLib');
|
|
70
|
-
}
|
|
71
|
-
const mapboxgl = 'Map' in module ? module : module.default;
|
|
72
|
-
if (!mapboxgl.Map) {
|
|
73
|
-
throw new Error('Invalid mapLib');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// workerUrl & workerClass may change the result of supported()
|
|
77
|
-
// https://github.com/visgl/react-map-gl/discussions/2027
|
|
78
|
-
setGlobals(mapboxgl, props);
|
|
79
|
-
if (!mapboxgl.supported || mapboxgl.supported(props)) {
|
|
80
|
-
if (props.reuseMaps) {
|
|
81
|
-
mapbox = Mapbox.reuse(props, containerRef.current);
|
|
82
|
-
}
|
|
83
|
-
if (!mapbox) {
|
|
84
|
-
mapbox = new Mapbox(mapboxgl.Map, props, containerRef.current);
|
|
85
|
-
}
|
|
86
|
-
contextValue.map = createRef(mapbox);
|
|
87
|
-
contextValue.mapLib = mapboxgl;
|
|
88
|
-
|
|
89
|
-
setMapInstance(mapbox);
|
|
90
|
-
mountedMapsContext?.onMapMount(contextValue.map, props.id);
|
|
91
|
-
} else {
|
|
92
|
-
throw new Error('Map is not supported by this browser');
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
.catch(error => {
|
|
96
|
-
const {onError} = props;
|
|
97
|
-
if (onError) {
|
|
98
|
-
onError({
|
|
99
|
-
type: 'error',
|
|
100
|
-
target: null,
|
|
101
|
-
originalEvent: null,
|
|
102
|
-
error
|
|
103
|
-
});
|
|
104
|
-
} else {
|
|
105
|
-
console.error(error); // eslint-disable-line
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
return () => {
|
|
110
|
-
isMounted = false;
|
|
111
|
-
if (mapbox) {
|
|
112
|
-
mountedMapsContext?.onMapUnmount(props.id);
|
|
113
|
-
if (props.reuseMaps) {
|
|
114
|
-
mapbox.recycle();
|
|
115
|
-
} else {
|
|
116
|
-
mapbox.destroy();
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}, []);
|
|
121
|
-
|
|
122
|
-
useIsomorphicLayoutEffect(() => {
|
|
123
|
-
if (mapInstance) {
|
|
124
|
-
mapInstance.setProps(props);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
useImperativeHandle(ref, () => contextValue.map, [mapInstance]);
|
|
129
|
-
|
|
130
|
-
const style: CSSProperties = useMemo(
|
|
131
|
-
() => ({
|
|
132
|
-
position: 'relative',
|
|
133
|
-
width: '100%',
|
|
134
|
-
height: '100%',
|
|
135
|
-
...props.style
|
|
136
|
-
}),
|
|
137
|
-
[props.style]
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
const CHILD_CONTAINER_STYLE = {
|
|
141
|
-
height: '100%'
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<div id={props.id} ref={containerRef} style={style}>
|
|
146
|
-
{mapInstance && (
|
|
147
|
-
<MapContext.Provider value={contextValue}>
|
|
148
|
-
<div mapboxgl-children="" style={CHILD_CONTAINER_STYLE}>
|
|
149
|
-
{props.children}
|
|
150
|
-
</div>
|
|
151
|
-
</MapContext.Provider>
|
|
152
|
-
)}
|
|
153
|
-
</div>
|
|
154
|
-
);
|
|
155
|
-
}
|
package/src/components/marker.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/* global document */
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import {createPortal} from 'react-dom';
|
|
4
|
-
import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react';
|
|
5
|
-
import {applyReactStyle} from '../utils/apply-react-style';
|
|
6
|
-
|
|
7
|
-
import type {MarkerEvent, MarkerDragEvent, PointLike, MarkerInstance} from '../types';
|
|
8
|
-
|
|
9
|
-
import {MapContext} from './map';
|
|
10
|
-
import {arePointsEqual} from '../utils/deep-equal';
|
|
11
|
-
|
|
12
|
-
export type MarkerProps<OptionsT, MarkerT extends MarkerInstance> = OptionsT & {
|
|
13
|
-
/** Longitude of the anchor location */
|
|
14
|
-
longitude: number;
|
|
15
|
-
/** Latitude of the anchor location */
|
|
16
|
-
latitude: number;
|
|
17
|
-
|
|
18
|
-
// These types will be further constraint by OptionsT
|
|
19
|
-
draggable?: boolean;
|
|
20
|
-
offset?: PointLike;
|
|
21
|
-
pitchAlignment?: string;
|
|
22
|
-
rotation?: number;
|
|
23
|
-
rotationAlignment?: string;
|
|
24
|
-
popup?: any;
|
|
25
|
-
|
|
26
|
-
/** CSS style override, applied to the control's container */
|
|
27
|
-
style?: React.CSSProperties;
|
|
28
|
-
onClick?: (e: MarkerEvent<MarkerT, MouseEvent>) => void;
|
|
29
|
-
onDragStart?: (e: MarkerDragEvent<MarkerT>) => void;
|
|
30
|
-
onDrag?: (e: MarkerDragEvent<MarkerT>) => void;
|
|
31
|
-
onDragEnd?: (e: MarkerDragEvent<MarkerT>) => void;
|
|
32
|
-
children?: React.ReactNode;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/* eslint-disable complexity,max-statements */
|
|
36
|
-
function Marker<MarkerOptions, MarkerT extends MarkerInstance>(
|
|
37
|
-
props: MarkerProps<MarkerOptions, MarkerT>,
|
|
38
|
-
ref: React.Ref<MarkerT>
|
|
39
|
-
) {
|
|
40
|
-
const {map, mapLib} = useContext(MapContext);
|
|
41
|
-
const thisRef = useRef({props});
|
|
42
|
-
thisRef.current.props = props;
|
|
43
|
-
|
|
44
|
-
const marker: MarkerT = useMemo(() => {
|
|
45
|
-
let hasChildren = false;
|
|
46
|
-
React.Children.forEach(props.children, el => {
|
|
47
|
-
if (el) {
|
|
48
|
-
hasChildren = true;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
const options = {
|
|
52
|
-
...props,
|
|
53
|
-
element: hasChildren ? document.createElement('div') : null
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const mk = new mapLib.Marker(options) as MarkerT;
|
|
57
|
-
mk.setLngLat([props.longitude, props.latitude]);
|
|
58
|
-
|
|
59
|
-
mk.getElement().addEventListener('click', (e: MouseEvent) => {
|
|
60
|
-
thisRef.current.props.onClick?.({
|
|
61
|
-
type: 'click',
|
|
62
|
-
target: mk,
|
|
63
|
-
originalEvent: e
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
mk.on('dragstart', e => {
|
|
68
|
-
const evt = e as MarkerDragEvent<MarkerT>;
|
|
69
|
-
evt.lngLat = marker.getLngLat();
|
|
70
|
-
thisRef.current.props.onDragStart?.(evt);
|
|
71
|
-
});
|
|
72
|
-
mk.on('drag', e => {
|
|
73
|
-
const evt = e as MarkerDragEvent<MarkerT>;
|
|
74
|
-
evt.lngLat = marker.getLngLat();
|
|
75
|
-
thisRef.current.props.onDrag?.(evt);
|
|
76
|
-
});
|
|
77
|
-
mk.on('dragend', e => {
|
|
78
|
-
const evt = e as MarkerDragEvent<MarkerT>;
|
|
79
|
-
evt.lngLat = marker.getLngLat();
|
|
80
|
-
thisRef.current.props.onDragEnd?.(evt);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return mk;
|
|
84
|
-
}, []);
|
|
85
|
-
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
marker.addTo(map.getMap());
|
|
88
|
-
|
|
89
|
-
return () => {
|
|
90
|
-
marker.remove();
|
|
91
|
-
};
|
|
92
|
-
}, []);
|
|
93
|
-
|
|
94
|
-
const {
|
|
95
|
-
longitude,
|
|
96
|
-
latitude,
|
|
97
|
-
offset,
|
|
98
|
-
style,
|
|
99
|
-
draggable = false,
|
|
100
|
-
popup = null,
|
|
101
|
-
rotation = 0,
|
|
102
|
-
rotationAlignment = 'auto',
|
|
103
|
-
pitchAlignment = 'auto'
|
|
104
|
-
} = props;
|
|
105
|
-
|
|
106
|
-
useEffect(() => {
|
|
107
|
-
applyReactStyle(marker.getElement(), style);
|
|
108
|
-
}, [style]);
|
|
109
|
-
|
|
110
|
-
useImperativeHandle(ref, () => marker, []);
|
|
111
|
-
|
|
112
|
-
if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) {
|
|
113
|
-
marker.setLngLat([longitude, latitude]);
|
|
114
|
-
}
|
|
115
|
-
if (offset && !arePointsEqual(marker.getOffset(), offset)) {
|
|
116
|
-
marker.setOffset(offset);
|
|
117
|
-
}
|
|
118
|
-
if (marker.isDraggable() !== draggable) {
|
|
119
|
-
marker.setDraggable(draggable);
|
|
120
|
-
}
|
|
121
|
-
if (marker.getRotation() !== rotation) {
|
|
122
|
-
marker.setRotation(rotation);
|
|
123
|
-
}
|
|
124
|
-
if (marker.getRotationAlignment() !== rotationAlignment) {
|
|
125
|
-
marker.setRotationAlignment(rotationAlignment);
|
|
126
|
-
}
|
|
127
|
-
if (marker.getPitchAlignment() !== pitchAlignment) {
|
|
128
|
-
marker.setPitchAlignment(pitchAlignment);
|
|
129
|
-
}
|
|
130
|
-
if (marker.getPopup() !== popup) {
|
|
131
|
-
marker.setPopup(popup);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return createPortal(props.children, marker.getElement());
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export default memo(forwardRef(Marker));
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import {useEffect, memo} from 'react';
|
|
3
|
-
import {applyReactStyle} from '../utils/apply-react-style';
|
|
4
|
-
import useControl from './use-control';
|
|
5
|
-
|
|
6
|
-
import type {ControlPosition, NavigationControlInstance} from '../types';
|
|
7
|
-
|
|
8
|
-
export type NavigationControlProps<OptionsT> = OptionsT & {
|
|
9
|
-
/** Placement of the control relative to the map. */
|
|
10
|
-
position?: ControlPosition;
|
|
11
|
-
/** CSS style override, applied to the control's container */
|
|
12
|
-
style?: React.CSSProperties;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
function NavigationControl<NavigationControlOptions, ControlT extends NavigationControlInstance>(
|
|
16
|
-
props: NavigationControlProps<NavigationControlOptions>
|
|
17
|
-
): null {
|
|
18
|
-
const ctrl = useControl<ControlT>(({mapLib}) => new mapLib.NavigationControl(props) as ControlT, {
|
|
19
|
-
position: props.position
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
applyReactStyle(ctrl._container, props.style);
|
|
24
|
-
}, [props.style]);
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default memo(NavigationControl);
|
package/src/components/popup.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/* global document */
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import {createPortal} from 'react-dom';
|
|
4
|
-
import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react';
|
|
5
|
-
import {applyReactStyle} from '../utils/apply-react-style';
|
|
6
|
-
|
|
7
|
-
import type {PopupEvent, PopupInstance} from '../types';
|
|
8
|
-
|
|
9
|
-
import {MapContext} from './map';
|
|
10
|
-
import {deepEqual} from '../utils/deep-equal';
|
|
11
|
-
|
|
12
|
-
export type PopupProps<OptionsT, PopupT extends PopupInstance> = OptionsT & {
|
|
13
|
-
/** Longitude of the anchor location */
|
|
14
|
-
longitude: number;
|
|
15
|
-
/** Latitude of the anchor location */
|
|
16
|
-
latitude: number;
|
|
17
|
-
|
|
18
|
-
// These types will be further constraint by OptionsT
|
|
19
|
-
anchor?: string;
|
|
20
|
-
offset?: any;
|
|
21
|
-
className?: string;
|
|
22
|
-
maxWidth?: string;
|
|
23
|
-
|
|
24
|
-
/** CSS style override, applied to the control's container */
|
|
25
|
-
style?: React.CSSProperties;
|
|
26
|
-
|
|
27
|
-
onOpen?: (e: PopupEvent<PopupT>) => void;
|
|
28
|
-
onClose?: (e: PopupEvent<PopupT>) => void;
|
|
29
|
-
children?: React.ReactNode;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// Adapted from https://github.com/mapbox/mapbox-gl-js/blob/v1.13.0/src/ui/popup.js
|
|
33
|
-
function getClassList(className: string) {
|
|
34
|
-
return new Set(className ? className.trim().split(/\s+/) : []);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* eslint-disable complexity,max-statements */
|
|
38
|
-
function Popup<PopupOptions, PopupT extends PopupInstance>(
|
|
39
|
-
props: PopupProps<PopupOptions, PopupT>,
|
|
40
|
-
ref: React.Ref<PopupT>
|
|
41
|
-
) {
|
|
42
|
-
const {map, mapLib} = useContext(MapContext);
|
|
43
|
-
const container = useMemo(() => {
|
|
44
|
-
return document.createElement('div');
|
|
45
|
-
}, []);
|
|
46
|
-
const thisRef = useRef({props});
|
|
47
|
-
thisRef.current.props = props;
|
|
48
|
-
|
|
49
|
-
const popup: PopupT = useMemo(() => {
|
|
50
|
-
const options = {...props};
|
|
51
|
-
const pp = new mapLib.Popup(options) as PopupT;
|
|
52
|
-
pp.setLngLat([props.longitude, props.latitude]);
|
|
53
|
-
pp.once('open', e => {
|
|
54
|
-
thisRef.current.props.onOpen?.(e as PopupEvent<PopupT>);
|
|
55
|
-
});
|
|
56
|
-
return pp;
|
|
57
|
-
}, []);
|
|
58
|
-
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
const onClose = e => {
|
|
61
|
-
thisRef.current.props.onClose?.(e as PopupEvent<PopupT>);
|
|
62
|
-
};
|
|
63
|
-
popup.on('close', onClose);
|
|
64
|
-
popup.setDOMContent(container).addTo(map.getMap());
|
|
65
|
-
|
|
66
|
-
return () => {
|
|
67
|
-
// https://github.com/visgl/react-map-gl/issues/1825
|
|
68
|
-
// onClose should not be fired if the popup is removed by unmounting
|
|
69
|
-
// When using React strict mode, the component is mounted twice.
|
|
70
|
-
// Firing the onClose callback here would be a false signal to remove the component.
|
|
71
|
-
popup.off('close', onClose);
|
|
72
|
-
if (popup.isOpen()) {
|
|
73
|
-
popup.remove();
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}, []);
|
|
77
|
-
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
applyReactStyle(popup.getElement(), props.style);
|
|
80
|
-
}, [props.style]);
|
|
81
|
-
|
|
82
|
-
useImperativeHandle(ref, () => popup, []);
|
|
83
|
-
|
|
84
|
-
if (popup.isOpen()) {
|
|
85
|
-
if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) {
|
|
86
|
-
popup.setLngLat([props.longitude, props.latitude]);
|
|
87
|
-
}
|
|
88
|
-
if (props.offset && !deepEqual(popup.options.offset, props.offset)) {
|
|
89
|
-
popup.setOffset(props.offset);
|
|
90
|
-
}
|
|
91
|
-
if (popup.options.anchor !== props.anchor || popup.options.maxWidth !== props.maxWidth) {
|
|
92
|
-
popup.options.anchor = props.anchor;
|
|
93
|
-
popup.setMaxWidth(props.maxWidth);
|
|
94
|
-
}
|
|
95
|
-
if (popup.options.className !== props.className) {
|
|
96
|
-
const prevClassList = getClassList(popup.options.className);
|
|
97
|
-
const nextClassList = getClassList(props.className);
|
|
98
|
-
|
|
99
|
-
for (const c of prevClassList) {
|
|
100
|
-
if (!nextClassList.has(c)) {
|
|
101
|
-
popup.removeClassName(c);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
for (const c of nextClassList) {
|
|
105
|
-
if (!prevClassList.has(c)) {
|
|
106
|
-
popup.addClassName(c);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
popup.options.className = props.className;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return createPortal(props.children, container);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export default memo(forwardRef(Popup));
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import {useEffect, useRef, memo} from 'react';
|
|
3
|
-
import {applyReactStyle} from '../utils/apply-react-style';
|
|
4
|
-
import useControl from './use-control';
|
|
5
|
-
|
|
6
|
-
import type {ControlPosition, ScaleControlInstance} from '../types';
|
|
7
|
-
|
|
8
|
-
export type ScaleControlProps<OptionsT> = OptionsT & {
|
|
9
|
-
// These props will be further constraint by OptionsT
|
|
10
|
-
unit?: string;
|
|
11
|
-
maxWidth?: number;
|
|
12
|
-
|
|
13
|
-
/** Placement of the control relative to the map. */
|
|
14
|
-
position?: ControlPosition;
|
|
15
|
-
/** CSS style override, applied to the control's container */
|
|
16
|
-
style?: React.CSSProperties;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function ScaleControl<ScaleControlOptions, ControlT extends ScaleControlInstance>(
|
|
20
|
-
props: ScaleControlProps<ScaleControlOptions>
|
|
21
|
-
): null {
|
|
22
|
-
const ctrl = useControl<ControlT>(({mapLib}) => new mapLib.ScaleControl(props) as ControlT, {
|
|
23
|
-
position: props.position
|
|
24
|
-
});
|
|
25
|
-
const propsRef = useRef<ScaleControlProps<ScaleControlOptions>>(props);
|
|
26
|
-
|
|
27
|
-
const prevProps = propsRef.current;
|
|
28
|
-
propsRef.current = props;
|
|
29
|
-
|
|
30
|
-
const {style} = props;
|
|
31
|
-
|
|
32
|
-
if (props.maxWidth !== undefined && props.maxWidth !== prevProps.maxWidth) {
|
|
33
|
-
ctrl.options.maxWidth = props.maxWidth;
|
|
34
|
-
}
|
|
35
|
-
if (props.unit !== undefined && props.unit !== prevProps.unit) {
|
|
36
|
-
ctrl.setUnit(props.unit);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
applyReactStyle(ctrl._container, style);
|
|
41
|
-
}, [style]);
|
|
42
|
-
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export default memo(ScaleControl);
|
package/src/components/source.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import {useContext, useEffect, useMemo, useState, useRef} from 'react';
|
|
3
|
-
import {cloneElement} from 'react';
|
|
4
|
-
import {MapContext} from './map';
|
|
5
|
-
import assert from '../utils/assert';
|
|
6
|
-
import {deepEqual} from '../utils/deep-equal';
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
MapInstance,
|
|
10
|
-
ISource,
|
|
11
|
-
CustomSource,
|
|
12
|
-
GeoJSONSourceImplementation,
|
|
13
|
-
ImageSourceImplemtation,
|
|
14
|
-
AnySourceImplementation
|
|
15
|
-
} from '../types';
|
|
16
|
-
import type {GeoJSONSourceRaw, ImageSourceRaw, VectorSourceRaw} from '../types/style-spec-bkoi-gl';
|
|
17
|
-
|
|
18
|
-
export type SourceProps<SourceT> = (SourceT | CustomSource) & {
|
|
19
|
-
id?: string;
|
|
20
|
-
children?: any;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
let sourceCounter = 0;
|
|
24
|
-
|
|
25
|
-
function createSource<SourceT extends ISource>(
|
|
26
|
-
map: MapInstance,
|
|
27
|
-
id: string,
|
|
28
|
-
props: SourceProps<SourceT>
|
|
29
|
-
) {
|
|
30
|
-
// @ts-ignore
|
|
31
|
-
if (map.style && map.style._loaded) {
|
|
32
|
-
const options = {...props};
|
|
33
|
-
delete options.id;
|
|
34
|
-
delete options.children;
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
map.addSource(id, options);
|
|
37
|
-
return map.getSource(id);
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* eslint-disable complexity */
|
|
43
|
-
function updateSource<SourceT extends ISource>(
|
|
44
|
-
source: AnySourceImplementation,
|
|
45
|
-
props: SourceProps<SourceT>,
|
|
46
|
-
prevProps: SourceProps<SourceT>
|
|
47
|
-
) {
|
|
48
|
-
assert(props.id === prevProps.id, 'source id changed');
|
|
49
|
-
assert(props.type === prevProps.type, 'source type changed');
|
|
50
|
-
|
|
51
|
-
let changedKey = '';
|
|
52
|
-
let changedKeyCount = 0;
|
|
53
|
-
|
|
54
|
-
for (const key in props) {
|
|
55
|
-
if (key !== 'children' && key !== 'id' && !deepEqual(prevProps[key], props[key])) {
|
|
56
|
-
changedKey = key;
|
|
57
|
-
changedKeyCount++;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (!changedKeyCount) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const type = props.type;
|
|
66
|
-
|
|
67
|
-
if (type === 'geojson') {
|
|
68
|
-
(source as GeoJSONSourceImplementation).setData(
|
|
69
|
-
(props as unknown as GeoJSONSourceRaw).data as any
|
|
70
|
-
);
|
|
71
|
-
} else if (type === 'image') {
|
|
72
|
-
(source as ImageSourceImplemtation).updateImage({
|
|
73
|
-
url: (props as unknown as ImageSourceRaw).url,
|
|
74
|
-
coordinates: (props as unknown as ImageSourceRaw).coordinates
|
|
75
|
-
});
|
|
76
|
-
} else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') {
|
|
77
|
-
source.setCoordinates((props as ImageSourceRaw).coordinates);
|
|
78
|
-
} else if ('setUrl' in source) {
|
|
79
|
-
// Added in 1.12.0:
|
|
80
|
-
// vectorTileSource.setTiles
|
|
81
|
-
// vectorTileSource.setUrl
|
|
82
|
-
switch (changedKey) {
|
|
83
|
-
case 'url':
|
|
84
|
-
source.setUrl((props as VectorSourceRaw).url);
|
|
85
|
-
break;
|
|
86
|
-
case 'tiles':
|
|
87
|
-
source.setTiles((props as VectorSourceRaw).tiles);
|
|
88
|
-
break;
|
|
89
|
-
default:
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
// eslint-disable-next-line
|
|
93
|
-
console.warn(`Unable to update <Source> prop: ${changedKey}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
/* eslint-enable complexity */
|
|
97
|
-
|
|
98
|
-
function Source<SourceT extends ISource>(props: SourceProps<SourceT>) {
|
|
99
|
-
const map = useContext(MapContext).map.getMap();
|
|
100
|
-
const propsRef = useRef(props);
|
|
101
|
-
const [, setStyleLoaded] = useState(0);
|
|
102
|
-
|
|
103
|
-
const id = useMemo(() => props.id || `jsx-source-${sourceCounter++}`, []);
|
|
104
|
-
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
if (map) {
|
|
107
|
-
/* global setTimeout */
|
|
108
|
-
const forceUpdate = () => setTimeout(() => setStyleLoaded(version => version + 1), 0);
|
|
109
|
-
map.on('styledata', forceUpdate);
|
|
110
|
-
forceUpdate();
|
|
111
|
-
|
|
112
|
-
return () => {
|
|
113
|
-
map.off('styledata', forceUpdate);
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
if (map.style && map.style._loaded && map.getSource(id)) {
|
|
116
|
-
// Parent effects are destroyed before child ones, see
|
|
117
|
-
// https://github.com/facebook/react/issues/16728
|
|
118
|
-
// Source can only be removed after all child layers are removed
|
|
119
|
-
const allLayers = map.getStyle()?.layers;
|
|
120
|
-
if (allLayers) {
|
|
121
|
-
for (const layer of allLayers) {
|
|
122
|
-
// @ts-ignore (2339) source does not exist on all layer types
|
|
123
|
-
if (layer.source === id) {
|
|
124
|
-
map.removeLayer(layer.id);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
map.removeSource(id);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
return undefined;
|
|
133
|
-
}, [map]);
|
|
134
|
-
|
|
135
|
-
// @ts-ignore
|
|
136
|
-
let source = map && map.style && map.getSource(id);
|
|
137
|
-
if (source) {
|
|
138
|
-
updateSource(source, props, propsRef.current);
|
|
139
|
-
} else {
|
|
140
|
-
source = createSource(map, id, props);
|
|
141
|
-
}
|
|
142
|
-
propsRef.current = props;
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
(source &&
|
|
146
|
-
React.Children.map(
|
|
147
|
-
props.children,
|
|
148
|
-
child =>
|
|
149
|
-
child &&
|
|
150
|
-
cloneElement(child, {
|
|
151
|
-
source: id
|
|
152
|
-
})
|
|
153
|
-
)) ||
|
|
154
|
-
null
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export default Source;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {useContext, useMemo, useEffect} from 'react';
|
|
2
|
-
import type {IControl, ControlPosition} from '../types';
|
|
3
|
-
import {MapContext} from './map';
|
|
4
|
-
import type {MapContextValue} from './map';
|
|
5
|
-
|
|
6
|
-
type ControlOptions = {
|
|
7
|
-
position?: ControlPosition;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
function useControl<T extends IControl>(
|
|
11
|
-
onCreate: (context: MapContextValue) => T,
|
|
12
|
-
opts?: ControlOptions
|
|
13
|
-
): T;
|
|
14
|
-
|
|
15
|
-
function useControl<T extends IControl>(
|
|
16
|
-
onCreate: (context: MapContextValue) => T,
|
|
17
|
-
onRemove: (context: MapContextValue) => void,
|
|
18
|
-
opts?: ControlOptions
|
|
19
|
-
): T;
|
|
20
|
-
|
|
21
|
-
function useControl<T extends IControl>(
|
|
22
|
-
onCreate: (context: MapContextValue) => T,
|
|
23
|
-
onAdd: (context: MapContextValue) => void,
|
|
24
|
-
onRemove: (context: MapContextValue) => void,
|
|
25
|
-
opts?: ControlOptions
|
|
26
|
-
): T;
|
|
27
|
-
|
|
28
|
-
function useControl<T extends IControl>(
|
|
29
|
-
onCreate: (context: MapContextValue) => T,
|
|
30
|
-
arg1?: ((context: MapContextValue) => void) | ControlOptions,
|
|
31
|
-
arg2?: ((context: MapContextValue) => void) | ControlOptions,
|
|
32
|
-
arg3?: ControlOptions
|
|
33
|
-
): T {
|
|
34
|
-
const context = useContext(MapContext);
|
|
35
|
-
const ctrl = useMemo(() => onCreate(context), []);
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
const opts = (arg3 || arg2 || arg1) as ControlOptions;
|
|
39
|
-
const onAdd = typeof arg1 === 'function' && typeof arg2 === 'function' ? arg1 : null;
|
|
40
|
-
const onRemove = typeof arg2 === 'function' ? arg2 : typeof arg1 === 'function' ? arg1 : null;
|
|
41
|
-
|
|
42
|
-
const {map} = context;
|
|
43
|
-
if (!map.hasControl(ctrl)) {
|
|
44
|
-
map.addControl(ctrl, opts?.position);
|
|
45
|
-
if (onAdd) {
|
|
46
|
-
onAdd(context);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return () => {
|
|
51
|
-
if (onRemove) {
|
|
52
|
-
onRemove(context);
|
|
53
|
-
}
|
|
54
|
-
// Map might have been removed (parent effects are destroyed before child ones)
|
|
55
|
-
if (map.hasControl(ctrl)) {
|
|
56
|
-
map.removeControl(ctrl);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
}, []);
|
|
60
|
-
|
|
61
|
-
return ctrl;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export default useControl;
|