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.
Files changed (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -18
  3. package/dist/index.cjs +671 -736
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +370 -0
  6. package/dist/index.d.ts +370 -2
  7. package/dist/index.js +1434 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/styles/index.d.ts +4 -0
  10. package/dist/styles/react-bkoi-gl.css +1 -1
  11. package/package.json +84 -36
  12. package/bkoi-gl/package.json +0 -6
  13. package/dist/components/attribution-control.d.ts +0 -11
  14. package/dist/components/attribution-control.js +0 -19
  15. package/dist/components/attribution-control.js.map +0 -1
  16. package/dist/components/fullscreen-control.d.ts +0 -14
  17. package/dist/components/fullscreen-control.js +0 -21
  18. package/dist/components/fullscreen-control.js.map +0 -1
  19. package/dist/components/geolocate-control.d.ts +0 -37
  20. package/dist/components/geolocate-control.js +0 -46
  21. package/dist/components/geolocate-control.js.map +0 -1
  22. package/dist/components/layer.d.ts +0 -17
  23. package/dist/components/layer.js +0 -99
  24. package/dist/components/layer.js.map +0 -1
  25. package/dist/components/map.d.ts +0 -23
  26. package/dist/components/map.js +0 -102
  27. package/dist/components/map.js.map +0 -1
  28. package/dist/components/marker.d.ts +0 -41
  29. package/dist/components/marker.js +0 -98
  30. package/dist/components/marker.js.map +0 -1
  31. package/dist/components/navigation-control.d.ts +0 -11
  32. package/dist/components/navigation-control.js +0 -19
  33. package/dist/components/navigation-control.js.map +0 -1
  34. package/dist/components/popup.d.ts +0 -33
  35. package/dist/components/popup.js +0 -79
  36. package/dist/components/popup.js.map +0 -1
  37. package/dist/components/scale-control.d.ts +0 -13
  38. package/dist/components/scale-control.js +0 -31
  39. package/dist/components/scale-control.js.map +0 -1
  40. package/dist/components/source.d.ts +0 -7
  41. package/dist/components/source.js +0 -97
  42. package/dist/components/source.js.map +0 -1
  43. package/dist/components/use-control.d.ts +0 -9
  44. package/dist/components/use-control.js +0 -31
  45. package/dist/components/use-control.js.map +0 -1
  46. package/dist/components/use-map.d.ts +0 -20
  47. package/dist/components/use-map.js +0 -54
  48. package/dist/components/use-map.js.map +0 -1
  49. package/dist/exports-bkoi-gl.cjs +0 -1512
  50. package/dist/exports-bkoi-gl.d.ts +0 -89
  51. package/dist/exports-bkoi-gl.js +0 -36
  52. package/dist/exports-bkoi-gl.js.map +0 -1
  53. package/dist/exports-mapbox.d.ts +0 -139
  54. package/dist/exports-mapbox.js +0 -36
  55. package/dist/exports-mapbox.js.map +0 -1
  56. package/dist/mapbox/create-ref.d.ts +0 -9
  57. package/dist/mapbox/create-ref.js +0 -64
  58. package/dist/mapbox/create-ref.js.map +0 -1
  59. package/dist/mapbox/mapbox.d.ts +0 -81
  60. package/dist/mapbox/mapbox.js +0 -476
  61. package/dist/mapbox/mapbox.js.map +0 -1
  62. package/dist/types/common.d.ts +0 -78
  63. package/dist/types/common.js +0 -2
  64. package/dist/types/common.js.map +0 -1
  65. package/dist/types/events-bkoi-gl.d.ts +0 -49
  66. package/dist/types/events-bkoi-gl.js +0 -2
  67. package/dist/types/events-bkoi-gl.js.map +0 -1
  68. package/dist/types/events-mapbox.d.ts +0 -49
  69. package/dist/types/events-mapbox.js +0 -2
  70. package/dist/types/events-mapbox.js.map +0 -1
  71. package/dist/types/events.d.ts +0 -39
  72. package/dist/types/events.js +0 -2
  73. package/dist/types/events.js.map +0 -1
  74. package/dist/types/index.d.ts +0 -70
  75. package/dist/types/index.js +0 -5
  76. package/dist/types/index.js.map +0 -1
  77. package/dist/types/lib.d.ts +0 -224
  78. package/dist/types/lib.js +0 -2
  79. package/dist/types/lib.js.map +0 -1
  80. package/dist/types/public.d.ts +0 -2
  81. package/dist/types/public.js +0 -2
  82. package/dist/types/public.js.map +0 -1
  83. package/dist/types/style-spec-bkoi-gl.d.ts +0 -9
  84. package/dist/types/style-spec-bkoi-gl.js +0 -2
  85. package/dist/types/style-spec-bkoi-gl.js.map +0 -1
  86. package/dist/types/style-spec-mapbox.d.ts +0 -7
  87. package/dist/types/style-spec-mapbox.js +0 -2
  88. package/dist/types/style-spec-mapbox.js.map +0 -1
  89. package/dist/utils/apply-react-style.d.ts +0 -2
  90. package/dist/utils/apply-react-style.js +0 -16
  91. package/dist/utils/apply-react-style.js.map +0 -1
  92. package/dist/utils/assert.d.ts +0 -1
  93. package/dist/utils/assert.js +0 -6
  94. package/dist/utils/assert.js.map +0 -1
  95. package/dist/utils/deep-equal.d.ts +0 -15
  96. package/dist/utils/deep-equal.js +0 -46
  97. package/dist/utils/deep-equal.js.map +0 -1
  98. package/dist/utils/set-globals.d.ts +0 -22
  99. package/dist/utils/set-globals.js +0 -19
  100. package/dist/utils/set-globals.js.map +0 -1
  101. package/dist/utils/style-utils.d.ts +0 -2
  102. package/dist/utils/style-utils.js +0 -42
  103. package/dist/utils/style-utils.js.map +0 -1
  104. package/dist/utils/transform.d.ts +0 -26
  105. package/dist/utils/transform.js +0 -56
  106. package/dist/utils/transform.js.map +0 -1
  107. package/dist/utils/use-isomorphic-layout-effect.d.ts +0 -3
  108. package/dist/utils/use-isomorphic-layout-effect.js +0 -4
  109. package/dist/utils/use-isomorphic-layout-effect.js.map +0 -1
  110. package/src/components/attribution-control.ts +0 -32
  111. package/src/components/fullscreen-control.tsx +0 -37
  112. package/src/components/geolocate-control.ts +0 -90
  113. package/src/components/layer.ts +0 -133
  114. package/src/components/map.tsx +0 -155
  115. package/src/components/marker.ts +0 -137
  116. package/src/components/navigation-control.ts +0 -29
  117. package/src/components/popup.ts +0 -116
  118. package/src/components/scale-control.ts +0 -46
  119. package/src/components/source.ts +0 -158
  120. package/src/components/use-control.ts +0 -64
  121. package/src/components/use-map.tsx +0 -69
  122. package/src/exports-bkoi-gl.ts +0 -156
  123. package/src/exports-mapbox.ts +0 -159
  124. package/src/index.ts +0 -2
  125. package/src/mapbox/create-ref.ts +0 -118
  126. package/src/mapbox/mapbox.ts +0 -742
  127. package/src/types/common.ts +0 -94
  128. package/src/types/events-bkoi-gl.ts +0 -78
  129. package/src/types/events-mapbox.ts +0 -76
  130. package/src/types/events.ts +0 -73
  131. package/src/types/index.ts +0 -93
  132. package/src/types/lib.ts +0 -279
  133. package/src/types/public.ts +0 -9
  134. package/src/types/style-spec-bkoi-gl.ts +0 -81
  135. package/src/types/style-spec-mapbox.ts +0 -80
  136. package/src/utils/apply-react-style.ts +0 -20
  137. package/src/utils/assert.ts +0 -5
  138. package/src/utils/deep-equal.ts +0 -61
  139. package/src/utils/set-globals.ts +0 -57
  140. package/src/utils/style-utils.ts +0 -59
  141. package/src/utils/transform.ts +0 -86
  142. package/src/utils/use-isomorphic-layout-effect.ts +0 -7
@@ -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
- }
@@ -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);
@@ -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);
@@ -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;