@maplibre/maplibre-react-native 10.0.0-beta.13 → 10.0.0-beta.15

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 (36) hide show
  1. package/README.md +9 -11
  2. package/android/src/main/java/org/maplibre/reactnative/components/camera/MLRNCamera.java +37 -48
  3. package/android/src/main/java/org/maplibre/reactnative/components/location/LocationComponentManager.java +16 -9
  4. package/android/src/main/java/org/maplibre/reactnative/utils/GeoJSONUtils.java +49 -24
  5. package/app.plugin.js +1 -1
  6. package/ios/MLRN/MLRNCamera.m +6 -7
  7. package/lib/commonjs/components/Camera.js +109 -60
  8. package/lib/commonjs/components/Camera.js.map +1 -1
  9. package/lib/commonjs/components/MapView.js +6 -6
  10. package/lib/commonjs/modules/offline/OfflineManager.js +8 -8
  11. package/lib/commonjs/plugin/withMapLibre.js +149 -0
  12. package/lib/commonjs/plugin/withMapLibre.js.map +1 -0
  13. package/lib/module/components/Camera.js +111 -62
  14. package/lib/module/components/Camera.js.map +1 -1
  15. package/lib/module/components/MapView.js +6 -6
  16. package/lib/module/modules/offline/OfflineManager.js +8 -8
  17. package/lib/module/plugin/withMapLibre.js +140 -0
  18. package/lib/module/plugin/withMapLibre.js.map +1 -0
  19. package/lib/typescript/commonjs/src/components/Camera.d.ts.map +1 -1
  20. package/lib/typescript/commonjs/src/modules/offline/OfflineManager.d.ts +8 -8
  21. package/{plugin/build → lib/typescript/commonjs/src/plugin}/withMapLibre.d.ts +1 -0
  22. package/lib/typescript/commonjs/src/plugin/withMapLibre.d.ts.map +1 -0
  23. package/lib/typescript/module/src/components/Camera.d.ts.map +1 -1
  24. package/lib/typescript/module/src/modules/offline/OfflineManager.d.ts +8 -8
  25. package/lib/typescript/module/src/plugin/withMapLibre.d.ts +13 -0
  26. package/lib/typescript/module/src/plugin/withMapLibre.d.ts.map +1 -0
  27. package/package.json +8 -10
  28. package/src/components/Camera.tsx +151 -73
  29. package/src/components/MapView.tsx +6 -6
  30. package/src/modules/offline/OfflineManager.ts +8 -8
  31. package/src/plugin/withMapLibre.ts +181 -0
  32. package/lib/typescript/commonjs/jest.config.d.ts +0 -2
  33. package/lib/typescript/commonjs/jest.config.d.ts.map +0 -1
  34. package/lib/typescript/module/jest.config.d.ts +0 -2
  35. package/lib/typescript/module/jest.config.d.ts.map +0 -1
  36. package/plugin/build/withMapLibre.js +0 -148
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  [![MapLibre Logo](https://maplibre.org/img/maplibre-logo-big.svg)](https://maplibre.org)
2
2
 
3
3
  # MapLibre React Native
4
+
4
5
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.md)
5
6
  [![Version](https://img.shields.io/npm/v/@maplibre/maplibre-react-native)](https://www.npmjs.com/package/@maplibre/maplibre-react-native)
6
- [![Actions](https://img.shields.io/github/actions/workflow/status/maplibre/maplibre-react-native/review.yml?label=Actions
7
- )](https://github.com/maplibre/maplibre-react-native/actions/workflows/review.yml)
8
-
7
+ [![Actions](https://img.shields.io/github/actions/workflow/status/maplibre/maplibre-react-native/review.yml?label=Actions)](https://github.com/maplibre/maplibre-react-native/actions/workflows/review.yml)
9
8
 
10
- _React Native library for creating maps with [MapLibre Native for Android & iOS](https://github.com/maplibre/maplibre-gl-native)_.
9
+ _React Native library for creating maps
10
+ with [MapLibre Native for Android & iOS](https://github.com/maplibre/maplibre-gl-native)._
11
11
 
12
12
  This project originated as a fork of [rnmapbox](https://github.com/rnmapbox/maps), a community-maintained
13
13
  React Native library for building maps with the Mapbox iOS and Android mobile SDKs. The original product
@@ -27,12 +27,10 @@ diverged, it has become necessary to separate the projects into specific wrapper
27
27
 
28
28
  ## Documentation
29
29
 
30
- - [Getting Started](/docs/guides/setup/GettingStarted.md)
30
+ - [Getting Started](/docs/guides/setup/Getting-Started)
31
31
  - Installation
32
- - React Native
33
- - [Android](/docs/guides/setup/Android.md)
34
- - [iOS](/docs/guides/setup/iOS.md)
35
32
  - [Expo](/docs/guides/setup/Expo.md)
33
+ - [React Native](/docs/guides/setup/React-Native.md)
36
34
  - Migrations
37
35
  - [Migrating to v10](/docs/guides/migrations/v10.md)
38
36
 
@@ -71,13 +69,13 @@ diverged, it has become necessary to separate the projects into specific wrapper
71
69
 
72
70
  ### Misc
73
71
 
74
- - [MLRNModule](/docs/guides/MLRNModule)
75
- - [Custom HTTP Headers](/docs/guides/CustomHTTPHeaders.md)
72
+ - [MLRNModule](/docs/guides/MLRNModule.md)
73
+ - [Custom HTTP Headers](/docs/guides/Custom-HTTP-Headers.md)
76
74
  - [Logger](/docs/guides/Logger.md)
77
75
 
78
76
  ## Contributing & Development
79
77
 
80
- Read the [CONTRIBUTING.md](CONTRIBUTING.md) guide in order to get familiar with how we do things around here and
78
+ Read the [CONTRIBUTING](/CONTRIBUTING.md) guide in order to get familiar with how we do things around here and
81
79
  set up your local development environment.
82
80
 
83
81
  ## Community
@@ -2,6 +2,7 @@ package org.maplibre.reactnative.components.camera;
2
2
 
3
3
  import android.content.Context;
4
4
  import android.location.Location;
5
+ import android.util.Log;
5
6
 
6
7
  import org.maplibre.android.camera.CameraPosition;
7
8
  import org.maplibre.android.camera.CameraUpdate;
@@ -11,13 +12,9 @@ import org.maplibre.android.geometry.LatLngBounds;
11
12
  import org.maplibre.android.geometry.VisibleRegion;
12
13
  import org.maplibre.android.location.OnCameraTrackingChangedListener;
13
14
  import org.maplibre.android.location.modes.CameraMode;
14
- import org.maplibre.android.location.modes.RenderMode;
15
15
  import org.maplibre.android.maps.MapLibreMap;
16
16
  import org.maplibre.android.maps.Style;
17
- import org.maplibre.android.location.LocationComponent;
18
- import org.maplibre.android.location.LocationComponentOptions;
19
- import org.maplibre.android.location.LocationComponentActivationOptions;
20
- // import org.maplibre.android.plugins.locationlayer.LocationLayerPlugin;
17
+
21
18
  import org.maplibre.reactnative.components.AbstractMapFeature;
22
19
  import org.maplibre.reactnative.components.location.LocationComponentManager;
23
20
  import org.maplibre.reactnative.components.mapview.MLRNMapView;
@@ -31,8 +28,6 @@ import org.maplibre.reactnative.location.UserTrackingMode;
31
28
  import org.maplibre.reactnative.location.UserTrackingState;
32
29
  import org.maplibre.reactnative.utils.GeoJSONUtils;
33
30
 
34
- import org.maplibre.reactnative.R;
35
-
36
31
  import org.maplibre.reactnative.events.constants.EventTypes;
37
32
 
38
33
  import com.facebook.react.bridge.WritableMap;
@@ -87,12 +82,12 @@ public class MLRNCamera extends AbstractMapFeature {
87
82
  private LocationManager.OnUserLocationChange mLocationChangeListener = new LocationManager.OnUserLocationChange() {
88
83
  @Override
89
84
  public void onLocationChange(Location nextLocation) {
90
- if (getMapboxMap() == null || mLocationComponentManager == null || !mLocationComponentManager.hasLocationComponent() || (!mFollowUserLocation)) {
91
- return;
92
- }
85
+ if (getMapboxMap() == null || mLocationComponentManager == null || !mLocationComponentManager.hasLocationComponent() || (!mFollowUserLocation)) {
86
+ return;
87
+ }
93
88
 
94
- mUserLocation.setCurrentLocation(nextLocation);
95
- sendUserLocationUpdateEvent(nextLocation);
89
+ mUserLocation.setCurrentLocation(nextLocation);
90
+ sendUserLocationUpdateEvent(nextLocation);
96
91
  }
97
92
  };
98
93
 
@@ -236,12 +231,7 @@ public class MLRNCamera extends AbstractMapFeature {
236
231
  }
237
232
  }
238
233
 
239
- return new CameraPosition.Builder()
240
- .target(center)
241
- .bearing(getDirectionForUserLocationUpdate())
242
- .tilt(mPitch)
243
- .zoom(zoomLevel)
244
- .build();
234
+ return new CameraPosition.Builder().target(center).bearing(getDirectionForUserLocationUpdate()).tilt(mPitch).zoom(zoomLevel).build();
245
235
  }
246
236
 
247
237
  private double getDirectionForUserLocationUpdate() {
@@ -260,7 +250,7 @@ public class MLRNCamera extends AbstractMapFeature {
260
250
  }
261
251
 
262
252
  private void sendUserLocationUpdateEvent(Location location) {
263
- if(location == null){
253
+ if (location == null) {
264
254
  return;
265
255
  }
266
256
  IEvent event = new MapChangeEvent(this, EventTypes.USER_LOCATION_UPDATED, makeLocationChangePayload(location));
@@ -376,37 +366,38 @@ public class MLRNCamera extends AbstractMapFeature {
376
366
  }
377
367
 
378
368
  mLocationComponentManager.update(style);
379
-
380
- if (mFollowUserLocation) {
381
- mLocationComponentManager.setCameraMode(UserTrackingMode.getCameraMode(mUserTrackingMode));
382
- }
383
369
  mLocationComponentManager.setFollowUserLocation(mFollowUserLocation);
384
370
 
385
371
  if (mFollowUserLocation) {
386
372
  mLocationComponentManager.setCameraMode(UserTrackingMode.getCameraMode(mUserTrackingMode));
387
373
  mLocationComponentManager.addOnCameraTrackingChangedListener(new OnCameraTrackingChangedListener() {
388
- @Override public void onCameraTrackingChanged(int currentMode) {
389
- int userTrackingMode = UserTrackingMode.NONE;
390
- switch (currentMode) {
391
- case CameraMode.NONE:
392
- userTrackingMode = UserTrackingMode.NONE;
393
- break;
394
- case CameraMode.TRACKING:
395
- userTrackingMode = UserTrackingMode.FOLLOW;
396
- break;
397
- case CameraMode.TRACKING_COMPASS:
398
- userTrackingMode = UserTrackingMode.FollowWithHeading;
399
- break;
400
- case CameraMode.TRACKING_GPS:
401
- userTrackingMode = UserTrackingMode.FollowWithCourse;
402
- break;
403
- default:
404
- userTrackingMode = UserTrackingMode.NONE;
405
- }
406
- updateUserTrackingMode(userTrackingMode);
407
- }
408
- @Override public void onCameraTrackingDismissed() {
374
+ @Override
375
+ public void onCameraTrackingChanged(int currentMode) {
376
+ int userTrackingMode;
377
+
378
+ switch (currentMode) {
379
+ case CameraMode.NONE:
380
+ userTrackingMode = UserTrackingMode.NONE;
381
+ break;
382
+ case CameraMode.TRACKING:
383
+ userTrackingMode = UserTrackingMode.FOLLOW;
384
+ break;
385
+ case CameraMode.TRACKING_COMPASS:
386
+ userTrackingMode = UserTrackingMode.FollowWithHeading;
387
+ break;
388
+ case CameraMode.TRACKING_GPS:
389
+ userTrackingMode = UserTrackingMode.FollowWithCourse;
390
+ break;
391
+ default:
392
+ userTrackingMode = UserTrackingMode.NONE;
409
393
  }
394
+
395
+ updateUserTrackingMode(userTrackingMode);
396
+ }
397
+
398
+ @Override
399
+ public void onCameraTrackingDismissed() {
400
+ }
410
401
  });
411
402
  } else {
412
403
  mLocationComponentManager.setCameraMode(CameraMode.NONE);
@@ -429,10 +420,7 @@ public class MLRNCamera extends AbstractMapFeature {
429
420
  }
430
421
 
431
422
  private CameraPosition buildCamera(CameraPosition previousPosition, boolean shouldUpdateTarget) {
432
- CameraPosition.Builder builder = new CameraPosition.Builder(previousPosition)
433
- .bearing(mHeading)
434
- .tilt(mPitch)
435
- .zoom(mZoomLevel);
423
+ CameraPosition.Builder builder = new CameraPosition.Builder(previousPosition).bearing(mHeading).tilt(mPitch).zoom(mZoomLevel);
436
424
 
437
425
  if (shouldUpdateTarget) {
438
426
  builder.target(GeoJSONUtils.toLatLng(mCenterCoordinate));
@@ -507,6 +495,7 @@ public class MLRNCamera extends AbstractMapFeature {
507
495
  /**
508
496
  * Create a payload of the location data per the web api geolocation spec
509
497
  * https://dev.w3.org/geo/api/spec-source.html#position
498
+ *
510
499
  * @return
511
500
  */
512
501
  private WritableMap makeLocationChangePayload(Location location) {
@@ -46,6 +46,8 @@ public class LocationComponentManager {
46
46
 
47
47
  private boolean mShowingUserLocation = false;
48
48
 
49
+ private OnCameraTrackingChangedListener mOnCameraTrackingChangedListener = null;
50
+
49
51
  public void showUserLocation(boolean showUserLocation) {
50
52
  mShowUserLocation = showUserLocation;
51
53
  stateChanged();
@@ -68,16 +70,21 @@ public class LocationComponentManager {
68
70
  }
69
71
 
70
72
  public void setPreferredFramesPerSecond(int preferredFramesPerSecond) {
71
- if(mLocationComponent == null || preferredFramesPerSecond <= 0) {
73
+ if (mLocationComponent == null || preferredFramesPerSecond <= 0) {
72
74
  return;
73
- }
75
+ }
74
76
 
75
77
  mLocationComponent.setMaxAnimationFps(preferredFramesPerSecond);
76
78
  }
77
79
 
78
-
79
80
  public void addOnCameraTrackingChangedListener(OnCameraTrackingChangedListener onCameraTrackingChangedListener) {
80
- mLocationComponent.addOnCameraTrackingChangedListener(onCameraTrackingChangedListener);
81
+ if (mOnCameraTrackingChangedListener != null) {
82
+ mLocationComponent.removeOnCameraTrackingChangedListener(mOnCameraTrackingChangedListener);
83
+ }
84
+
85
+ mOnCameraTrackingChangedListener = onCameraTrackingChangedListener;
86
+
87
+ mLocationComponent.addOnCameraTrackingChangedListener(mOnCameraTrackingChangedListener);
81
88
  }
82
89
 
83
90
  @SuppressLint("MissingPermission")
@@ -111,7 +118,7 @@ public class LocationComponentManager {
111
118
  public void update(boolean displayUserLocation, @NonNull Style style) {
112
119
  Integer tintColor = mMapView.getTintColor();
113
120
 
114
- if (mLocationComponent == null || tintColor != null ) {
121
+ if (mLocationComponent == null || tintColor != null) {
115
122
  mLocationComponent = mMap.getLocationComponent();
116
123
 
117
124
  LocationComponentActivationOptions locationComponentActivationOptions = LocationComponentActivationOptions
@@ -148,10 +155,10 @@ public class LocationComponentManager {
148
155
  .accuracyAlpha(0.0f);
149
156
  } else if (tintColor != null) {
150
157
  builder = builder
151
- .enableStaleState(false)
152
- .bearingTintColor(tintColor)
153
- .foregroundTintColor(tintColor)
154
- .accuracyColor(tintColor);
158
+ .enableStaleState(false)
159
+ .bearingTintColor(tintColor)
160
+ .foregroundTintColor(tintColor)
161
+ .accuracyColor(tintColor);
155
162
  }
156
163
  return builder.build();
157
164
  }
@@ -6,6 +6,8 @@ import com.facebook.react.bridge.WritableArray;
6
6
  import com.facebook.react.bridge.WritableMap;
7
7
  import com.facebook.react.bridge.WritableNativeArray;
8
8
  import com.facebook.react.bridge.WritableNativeMap;
9
+ import com.google.gson.JsonObject;
10
+
9
11
  import org.maplibre.geojson.Feature;
10
12
  import org.maplibre.geojson.FeatureCollection;
11
13
  import org.maplibre.geojson.Geometry;
@@ -19,23 +21,34 @@ import org.maplibre.geojson.Polygon;
19
21
  import org.maplibre.android.geometry.LatLng;
20
22
  import org.maplibre.android.geometry.LatLngBounds;
21
23
  import org.maplibre.android.geometry.LatLngQuad;
22
- import org.maplibre.android.style.light.Position;
24
+ import org.maplibre.android.log.Logger;
23
25
  import org.maplibre.turf.TurfMeasurement;
24
26
 
25
27
  import java.util.ArrayList;
26
28
  import java.util.List;
29
+ import java.util.stream.Collectors;
27
30
 
28
31
  public class GeoJSONUtils {
32
+ public static final String LOG_TAG = "GeoJSONUtils";
33
+
29
34
  public static WritableMap fromFeature(Feature feature) {
30
35
  WritableMap map = Arguments.createMap();
31
36
  map.putString("type", "Feature");
32
37
  map.putString("id", feature.id());
33
38
 
34
- WritableMap geometry = fromGeometry(feature.geometry());
35
- map.putMap("geometry", geometry);
39
+ Geometry geometry = feature.geometry();
40
+ if (geometry == null) {
41
+ map.putNull("geometry");
42
+ } else {
43
+ map.putMap("geometry", fromGeometry(geometry));
44
+ }
36
45
 
37
- WritableMap properties = ConvertUtils.toWritableMap(feature.properties());
38
- map.putMap("properties", properties);
46
+ JsonObject properties = feature.properties();
47
+ if(properties == null) {
48
+ map.putNull("properties");
49
+ } else {
50
+ map.putMap("properties", ConvertUtils.toWritableMap(properties));
51
+ }
39
52
 
40
53
  return map;
41
54
  }
@@ -43,22 +56,20 @@ public class GeoJSONUtils {
43
56
  public static WritableMap fromGeometry(Geometry geometry) {
44
57
  final String type = geometry.type();
45
58
 
46
- switch (type) {
47
- case "Point":
48
- return fromPoint((Point) geometry);
49
- case "LineString":
50
- return fromLineString((LineString) geometry);
51
- case "Polygon":
52
- return fromPolygon((Polygon) geometry);
53
- case "MultiPoint":
54
- return fromMultiPoint((MultiPoint) geometry);
55
- case "MultiLineString":
56
- return fromMultiLineString((MultiLineString) geometry);
57
- case "MultiPolygon":
58
- return fromMultiPolygon((MultiPolygon) geometry);
59
- default:
60
- return null;
61
- }
59
+ return switch (type) {
60
+ case "Point" -> fromPoint((Point) geometry);
61
+ case "LineString" -> fromLineString((LineString) geometry);
62
+ case "Polygon" -> fromPolygon((Polygon) geometry);
63
+ case "MultiPoint" -> fromMultiPoint((MultiPoint) geometry);
64
+ case "MultiLineString" -> fromMultiLineString((MultiLineString) geometry);
65
+ case "MultiPolygon" -> fromMultiPolygon((MultiPolygon) geometry);
66
+ case "GeometryCollection" -> fromGeometryCollection((GeometryCollection) geometry);
67
+ default -> {
68
+ Logger.w(LOG_TAG, "GeoJSONUtils.fromGeometry unsupported type: \"" + type + "\"");
69
+
70
+ yield null;
71
+ }
72
+ };
62
73
  }
63
74
 
64
75
  public static WritableMap fromPoint(Point point) {
@@ -103,6 +114,23 @@ public class GeoJSONUtils {
103
114
  return map;
104
115
  }
105
116
 
117
+ public static WritableMap fromGeometryCollection(GeometryCollection geometryCollection) {
118
+ WritableMap map = Arguments.createMap();
119
+ map.putString("type", "GeometryCollection");
120
+
121
+ map.putArray("geometries",
122
+ Arguments.fromList(
123
+ geometryCollection
124
+ .geometries()
125
+ .stream()
126
+ .map(GeoJSONUtils::fromGeometry)
127
+ .collect(Collectors.toList())
128
+ )
129
+ );
130
+
131
+ return map;
132
+ }
133
+
106
134
  public static WritableArray getCoordinates(Point point) {
107
135
  return Arguments.fromArray(pointToDoubleArray(point));
108
136
  }
@@ -122,9 +150,6 @@ public class GeoJSONUtils {
122
150
  WritableArray array = Arguments.createArray();
123
151
 
124
152
  List<List<Point>> points = polygon.coordinates();
125
- if (points == null) {
126
- return array;
127
- }
128
153
 
129
154
  for (List<Point> curPoint : points) {
130
155
  WritableArray innerArray = Arguments.createArray();
package/app.plugin.js CHANGED
@@ -1 +1 @@
1
- module.exports = require("./plugin/build/withMapLibre");
1
+ module.exports = require("./lib/commonjs/plugin/withMapLibre");
@@ -179,11 +179,6 @@
179
179
  return;
180
180
  }
181
181
 
182
- if (_map.userTrackingMode != [self _userTrackingMode]) {
183
- _map.showsUserLocation = [self _userTrackingMode] != MLNUserTrackingModeNone;
184
- _map.userTrackingMode = [self _userTrackingMode];
185
- }
186
-
187
182
  MLNMapCamera *camera = _map.camera;
188
183
  if (_followPitch != nil && [_followPitch floatValue] >= 0.0) {
189
184
  camera.pitch = [_followPitch floatValue];
@@ -202,8 +197,12 @@
202
197
  if (_followZoomLevel != nil && [_followZoomLevel doubleValue] >= 0.0) {
203
198
  camera.altitude = [_map altitudeFromZoom:[_followZoomLevel doubleValue]];
204
199
  }
205
-
206
- [_map setCamera:camera animated:YES];
200
+
201
+ [_map setCamera:camera animated:NO];
202
+
203
+ if (_map.userTrackingMode != [self _userTrackingMode]) {
204
+ [_map setUserTrackingMode:[self _userTrackingMode] animated:NO completionHandler:nil];
205
+ }
207
206
  }
208
207
 
209
208
  - (NSUInteger)_userTrackingMode
@@ -37,49 +37,52 @@ function makeNativeCameraStop(stop) {
37
37
  if (!stop) {
38
38
  return undefined;
39
39
  }
40
- const nativeStop = {};
40
+ const newNativeStop = {};
41
41
  if (stop.animationDuration !== undefined) {
42
- nativeStop.duration = stop.animationDuration;
42
+ newNativeStop.duration = stop.animationDuration;
43
43
  }
44
44
  if (stop.animationMode !== undefined) {
45
- nativeStop.mode = getNativeCameraMode(stop.animationMode);
45
+ newNativeStop.mode = getNativeCameraMode(stop.animationMode);
46
46
  }
47
47
  if (stop.centerCoordinate) {
48
- nativeStop.centerCoordinate = JSON.stringify((0, _helpers.point)(stop.centerCoordinate));
48
+ newNativeStop.centerCoordinate = JSON.stringify((0, _helpers.point)(stop.centerCoordinate));
49
49
  }
50
50
  if (stop.heading !== undefined) {
51
- nativeStop.heading = stop.heading;
51
+ newNativeStop.heading = stop.heading;
52
52
  }
53
53
  if (stop.pitch !== undefined) {
54
- nativeStop.pitch = stop.pitch;
54
+ newNativeStop.pitch = stop.pitch;
55
55
  }
56
56
  if (stop.zoomLevel !== undefined) {
57
- nativeStop.zoom = stop.zoomLevel;
57
+ newNativeStop.zoom = stop.zoomLevel;
58
58
  }
59
59
  if (stop.bounds && stop.bounds.ne && stop.bounds.sw) {
60
60
  const {
61
61
  ne,
62
62
  sw
63
63
  } = stop.bounds;
64
- nativeStop.bounds = (0, _makeNativeBounds.makeNativeBounds)(ne, sw);
64
+ newNativeStop.bounds = (0, _makeNativeBounds.makeNativeBounds)(ne, sw);
65
65
  }
66
66
  const paddingTop = stop.padding?.paddingTop ?? stop.bounds?.paddingTop;
67
67
  if (paddingTop !== undefined) {
68
- nativeStop.paddingTop = paddingTop;
68
+ newNativeStop.paddingTop = paddingTop;
69
69
  }
70
70
  const paddingRight = stop.padding?.paddingRight ?? stop.bounds?.paddingRight;
71
71
  if (paddingRight !== undefined) {
72
- nativeStop.paddingRight = paddingRight;
72
+ newNativeStop.paddingRight = paddingRight;
73
73
  }
74
74
  const paddingBottom = stop.padding?.paddingBottom ?? stop.bounds?.paddingBottom;
75
75
  if (paddingBottom !== undefined) {
76
- nativeStop.paddingBottom = paddingBottom;
76
+ newNativeStop.paddingBottom = paddingBottom;
77
77
  }
78
78
  const paddingLeft = stop.padding?.paddingLeft ?? stop.bounds?.paddingLeft;
79
79
  if (paddingLeft !== undefined) {
80
- nativeStop.paddingLeft = paddingLeft;
80
+ newNativeStop.paddingLeft = paddingLeft;
81
81
  }
82
- return nativeStop;
82
+ if (newNativeStop.centerCoordinate && newNativeStop.bounds) {
83
+ throw new Error("Create a camera stop with bounds and centerCoordinate – this is not possible.");
84
+ }
85
+ return newNativeStop;
83
86
  }
84
87
  const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _react.forwardRef)(({
85
88
  animationMode,
@@ -101,40 +104,19 @@ const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _
101
104
  pitch,
102
105
  zoomLevel
103
106
  }, ref) => {
104
- const nativeCamera = (0, _useNativeRef.useNativeRef)();
105
- const nativeStop = (0, _react.useMemo)(() => {
106
- return makeNativeCameraStop({
107
- animationDuration,
108
- animationMode,
109
- bounds,
110
- centerCoordinate,
111
- heading,
112
- padding,
113
- pitch,
114
- zoomLevel
115
- });
116
- }, [animationDuration, animationMode, bounds, centerCoordinate, heading, padding, pitch, zoomLevel]);
117
- const nativeDefaultStop = (0, _react.useMemo)(() => {
118
- return makeNativeCameraStop(defaultSettings);
119
- }, [defaultSettings]);
120
- const nativeMaxBounds = (0, _react.useMemo)(() => {
121
- if (!maxBounds?.ne || !maxBounds?.sw) {
122
- return undefined;
123
- }
124
- return (0, _makeNativeBounds.makeNativeBounds)(maxBounds.ne, maxBounds.sw);
125
- }, [maxBounds]);
107
+ const nativeCameraRef = (0, _useNativeRef.useNativeRef)();
126
108
  const setCamera = (config = {}) => {
127
109
  if ("stops" in config) {
128
- nativeCamera.current?.setNativeProps({
110
+ nativeCameraRef.current?.setNativeProps({
129
111
  stop: {
130
112
  stops: config.stops.map(stopItem => makeNativeCameraStop(stopItem)).filter(stopItem => !!stopItem)
131
113
  }
132
114
  });
133
115
  } else {
134
- const nativeStop = makeNativeCameraStop(config);
135
- if (nativeStop) {
136
- nativeCamera.current?.setNativeProps({
137
- stop: nativeStop
116
+ const stop = makeNativeCameraStop(config);
117
+ if (stop) {
118
+ nativeCameraRef.current?.setNativeProps({
119
+ stop
138
120
  });
139
121
  }
140
122
  }
@@ -200,10 +182,10 @@ const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _
200
182
  * cameraRef.current?.fitBounds([lng, lat], [lng, lat], [verticalPadding, horizontalPadding], 1000)
201
183
  * cameraRef.current?.fitBounds([lng, lat], [lng, lat], [top, right, bottom, left], 1000)
202
184
  *
203
- * @param {Array<Number>} ne - North east coordinate of bound
204
- * @param {Array<Number>} sw - South west coordinate of bound
205
- * @param {Number|Array<Number>|undefined} padding - Padding for the bounds
206
- * @param {Number=} animationDuration - Duration of camera animation
185
+ * @param {Array<number>} ne - North east coordinate of bound
186
+ * @param {Array<number>} sw - South west coordinate of bound
187
+ * @param {number|Array<number>|undefined} padding - Padding for the bounds
188
+ * @param {number=} animationDuration - Duration of camera animation
207
189
  * @return {void}
208
190
  */
209
191
  fitBounds,
@@ -214,8 +196,8 @@ const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _
214
196
  * cameraRef.current?.flyTo([lng, lat])
215
197
  * cameraRef.current?.flyTo([lng, lat], 12000)
216
198
  *
217
- * @param {Array<Number>} coordinates - Coordinates that map camera will jump to
218
- * @param {Number=} animationDuration - Duration of camera animation
199
+ * @param {Array<number>} coordinates - Coordinates that map camera will jump to
200
+ * @param {number=} animationDuration - Duration of camera animation
219
201
  * @return {void}
220
202
  */
221
203
  flyTo,
@@ -226,8 +208,8 @@ const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _
226
208
  * cameraRef.current?.moveTo([lng, lat], 200) // eases camera to new location based on duration
227
209
  * cameraRef.current?.moveTo([lng, lat]) // snaps camera to new location without any easing
228
210
  *
229
- * @param {Array<Number>} coordinates - Coordinates that map camera will move too
230
- * @param {Number=} animationDuration - Duration of camera animation
211
+ * @param {Array<number>} coordinates - Coordinates that map camera will move too
212
+ * @param {number=} animationDuration - Duration of camera animation
231
213
  * @return {void}
232
214
  */
233
215
  moveTo,
@@ -238,8 +220,8 @@ const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _
238
220
  * cameraRef.current?.zoomTo(16)
239
221
  * cameraRef.current?.zoomTo(16, 100)
240
222
  *
241
- * @param {Number} zoomLevel - Zoom level that the map camera will animate too
242
- * @param {Number=} animationDuration - Duration of camera animation
223
+ * @param {number} zoomLevel - Zoom level that the map camera will animate too
224
+ * @param {number=} animationDuration - Duration of camera animation
243
225
  * @return {void}
244
226
  */
245
227
  zoomTo,
@@ -264,19 +246,86 @@ const Camera = exports.Camera = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _
264
246
  */
265
247
  setCamera
266
248
  }));
249
+ const followProps = (0, _react.useMemo)(() => {
250
+ return {
251
+ followUserMode,
252
+ followPitch: followPitch ?? pitch,
253
+ followHeading: followHeading ?? heading,
254
+ followZoomLevel: followZoomLevel ?? zoomLevel
255
+ };
256
+ }, [followUserMode, followPitch, pitch, followHeading, heading, followZoomLevel, zoomLevel]);
257
+ (0, _react.useEffect)(() => {
258
+ if (followUserLocation) {
259
+ if (_reactNative.Platform.OS === "android") {
260
+ nativeCameraRef.current?.setNativeProps({
261
+ ...followProps,
262
+ followUserLocation
263
+ });
264
+ } else {
265
+ nativeCameraRef.current?.setNativeProps({
266
+ ...followProps
267
+ });
268
+ nativeCameraRef.current?.setNativeProps({
269
+ followUserLocation
270
+ });
271
+ }
272
+ } else {
273
+ nativeCameraRef.current?.setNativeProps({
274
+ followUserLocation
275
+ });
276
+ }
277
+ }, [followUserLocation, followProps]);
278
+ const nativeMaxBounds = (0, _react.useMemo)(() => {
279
+ if (!maxBounds?.ne || !maxBounds?.sw) {
280
+ return undefined;
281
+ }
282
+ return (0, _makeNativeBounds.makeNativeBounds)(maxBounds.ne, maxBounds.sw);
283
+ }, [maxBounds]);
284
+ (0, _react.useEffect)(() => {
285
+ if (!followUserLocation) {
286
+ nativeCameraRef.current?.setNativeProps({
287
+ maxBounds: nativeMaxBounds
288
+ });
289
+ }
290
+ }, [followUserLocation, nativeMaxBounds]);
291
+ (0, _react.useEffect)(() => {
292
+ if (!followUserLocation) {
293
+ nativeCameraRef.current?.setNativeProps({
294
+ minZoomLevel
295
+ });
296
+ }
297
+ }, [followUserLocation, minZoomLevel]);
298
+ (0, _react.useEffect)(() => {
299
+ if (!followUserLocation) {
300
+ nativeCameraRef.current?.setNativeProps({
301
+ maxZoomLevel
302
+ });
303
+ }
304
+ }, [followUserLocation, maxZoomLevel]);
305
+ const nativeStop = (0, _react.useMemo)(() => {
306
+ return makeNativeCameraStop({
307
+ animationDuration,
308
+ animationMode,
309
+ bounds,
310
+ centerCoordinate,
311
+ heading,
312
+ padding,
313
+ pitch,
314
+ zoomLevel
315
+ });
316
+ }, [animationDuration, animationMode, bounds, centerCoordinate, heading, padding, pitch, zoomLevel]);
317
+ (0, _react.useEffect)(() => {
318
+ if (!followUserLocation) {
319
+ nativeCameraRef.current?.setNativeProps({
320
+ stop: nativeStop
321
+ });
322
+ }
323
+ }, [followUserLocation, nativeStop]);
324
+ const [nativeDefaultStop] = (0, _react.useState)(makeNativeCameraStop(defaultSettings));
267
325
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(MLRNCamera, {
268
326
  testID: "Camera",
269
- ref: nativeCamera,
270
- stop: nativeStop,
327
+ ref: nativeCameraRef,
271
328
  defaultStop: nativeDefaultStop,
272
- maxBounds: nativeMaxBounds,
273
- followUserLocation: followUserLocation,
274
- followHeading: followHeading,
275
- followPitch: followPitch,
276
- followUserMode: followUserMode,
277
- followZoomLevel: followZoomLevel,
278
- maxZoomLevel: maxZoomLevel,
279
- minZoomLevel: minZoomLevel,
280
329
  onUserTrackingModeChange: onUserTrackingModeChange
281
330
  });
282
331
  }));