@maplibre/maplibre-react-native 10.0.0-alpha.5 → 10.0.0-alpha.7

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 (54) hide show
  1. package/.eslintrc.js +3 -1
  2. package/.yarn/sdks/eslint/bin/eslint.js +8 -1
  3. package/.yarn/sdks/eslint/lib/api.js +8 -1
  4. package/.yarn/sdks/eslint/lib/unsupported-api.js +8 -1
  5. package/.yarn/sdks/prettier/bin/prettier.cjs +8 -1
  6. package/.yarn/sdks/prettier/index.cjs +8 -1
  7. package/.yarn/sdks/typescript/bin/tsc +8 -1
  8. package/.yarn/sdks/typescript/bin/tsserver +8 -1
  9. package/.yarn/sdks/typescript/lib/tsc.js +8 -1
  10. package/.yarn/sdks/typescript/lib/tsserver.js +20 -6
  11. package/.yarn/sdks/typescript/lib/tsserverlibrary.js +20 -6
  12. package/.yarn/sdks/typescript/lib/typescript.js +8 -1
  13. package/CHANGELOG.md +57 -48
  14. package/CONTRIBUTING.md +10 -9
  15. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/MarkerViewManager.java +5 -3
  16. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNMapView.java +7 -7
  17. package/docs/Camera.md +3 -3
  18. package/docs/MapView.md +9 -33
  19. package/docs/UserLocation.md +10 -2
  20. package/docs/docs.json +17 -32
  21. package/docs/offlineManager.md +246 -0
  22. package/javascript/Maplibre.ts +5 -1
  23. package/javascript/components/BackgroundLayer.tsx +27 -20
  24. package/javascript/components/Callout.tsx +40 -40
  25. package/javascript/components/Camera.tsx +421 -478
  26. package/javascript/components/CircleLayer.tsx +29 -22
  27. package/javascript/components/FillExtrusionLayer.tsx +23 -23
  28. package/javascript/components/FillLayer.tsx +22 -19
  29. package/javascript/components/HeatmapLayer.tsx +21 -19
  30. package/javascript/components/ImageSource.tsx +25 -32
  31. package/javascript/components/Images.tsx +36 -35
  32. package/javascript/components/Light.tsx +20 -47
  33. package/javascript/components/LineLayer.tsx +23 -20
  34. package/javascript/components/MapView.tsx +604 -554
  35. package/javascript/components/MarkerView.tsx +23 -38
  36. package/javascript/components/NativeUserLocation.tsx +3 -5
  37. package/javascript/components/PointAnnotation.tsx +111 -87
  38. package/javascript/components/RasterLayer.tsx +21 -18
  39. package/javascript/components/RasterSource.tsx +39 -42
  40. package/javascript/components/ShapeSource.tsx +287 -239
  41. package/javascript/components/Style.tsx +1 -1
  42. package/javascript/components/SymbolLayer.tsx +34 -28
  43. package/javascript/components/UserLocation.tsx +164 -151
  44. package/javascript/components/VectorSource.tsx +128 -117
  45. package/javascript/components/annotations/Annotation.tsx +105 -79
  46. package/javascript/{components/AbstractLayer.tsx → hooks/useAbstractLayer.ts} +54 -37
  47. package/javascript/hooks/useAbstractSource.ts +34 -0
  48. package/javascript/hooks/useNativeBridge.ts +125 -0
  49. package/javascript/hooks/useNativeRef.ts +13 -0
  50. package/javascript/hooks/useOnce.ts +12 -0
  51. package/javascript/utils/Logger.ts +3 -3
  52. package/package.json +2 -1
  53. package/javascript/components/AbstractSource.tsx +0 -27
  54. package/javascript/components/NativeBridgeComponent.tsx +0 -117
@@ -1,3 +1,5 @@
1
+ import useNativeBridge from '../hooks/useNativeBridge';
2
+ import useOnce from '../hooks/useOnce';
1
3
  import {FilterExpression} from '../utils/MaplibreStyles';
2
4
  import {Location} from '../modules/location/locationManager';
3
5
  import {isFunction, isAndroid} from '../utils';
@@ -5,9 +7,18 @@ import {getFilter} from '../utils/filterUtils';
5
7
  import Logger from '../utils/Logger';
6
8
  import BaseProps from '../types/BaseProps';
7
9
 
8
- import NativeBridgeComponent from './NativeBridgeComponent';
9
-
10
- import React, {Component, ReactElement, ReactNode} from 'react';
10
+ import React, {
11
+ Component,
12
+ memo,
13
+ ReactElement,
14
+ ReactNode,
15
+ useCallback,
16
+ useEffect,
17
+ useImperativeHandle,
18
+ useMemo,
19
+ useRef,
20
+ useState,
21
+ } from 'react';
11
22
  import {
12
23
  View,
13
24
  StyleSheet,
@@ -15,7 +26,6 @@ import {
15
26
  requireNativeComponent,
16
27
  ViewProps,
17
28
  NativeMethods,
18
- LayoutChangeEvent,
19
29
  NativeSyntheticEvent,
20
30
  } from 'react-native';
21
31
  import debounce from 'debounce';
@@ -107,22 +117,10 @@ interface MapViewProps extends BaseProps {
107
117
  * Adds attribution offset, e.g. `{top: 8, left: 8}` will put attribution button in top-left corner of the map
108
118
  */
109
119
  attributionPosition?:
110
- | {
111
- top?: number;
112
- left?: number;
113
- }
114
- | {
115
- top?: number;
116
- right?: number;
117
- }
118
- | {
119
- bottom?: number;
120
- left?: number;
121
- }
122
- | {
123
- bottom?: number;
124
- right?: number;
125
- };
120
+ | {top?: number; left?: number}
121
+ | {top?: number; right?: number}
122
+ | {bottom?: number; left?: number}
123
+ | {bottom?: number; right?: number};
126
124
  /**
127
125
  * MapView's tintColor
128
126
  */
@@ -135,22 +133,10 @@ interface MapViewProps extends BaseProps {
135
133
  * Adds logo offset, e.g. `{top: 8, left: 8}` will put the logo in top-left corner of the map
136
134
  */
137
135
  logoPosition?:
138
- | {
139
- top?: number;
140
- left?: number;
141
- }
142
- | {
143
- top?: number;
144
- right?: number;
145
- }
146
- | {
147
- bottom?: number;
148
- left?: number;
149
- }
150
- | {
151
- bottom?: number;
152
- right?: number;
153
- };
136
+ | {top?: number; left?: number}
137
+ | {top?: number; right?: number}
138
+ | {bottom?: number; left?: number}
139
+ | {bottom?: number; right?: number};
154
140
  /**
155
141
  * Enable/Disable the compass from appearing on the map
156
142
  */
@@ -267,552 +253,616 @@ interface NativeProps extends Omit<MapViewProps, 'onPress' | 'onLongPress'> {
267
253
  onLongPress(event: NativeSyntheticEvent<{payload: GeoJSON.Feature}>): void;
268
254
  }
269
255
 
270
- export interface MapViewState {
271
- isReady: boolean;
272
- width: number;
273
- height: number;
274
- region: GeoJSON.Feature<GeoJSON.Point, RegionPayload> | null;
275
- isUserInteraction: boolean;
256
+ export interface MapViewRef {
257
+ getPointInView: (coordinate: GeoJSON.Position) => Promise<GeoJSON.Point>;
258
+ getCoordinateFromView: (point: number[]) => Promise<GeoJSON.Position>;
259
+ getVisibleBounds: () => Promise<VisibleBounds>;
260
+ queryRenderedFeaturesAtPoint: (
261
+ point: [screenPointX: number, screenPointY: number],
262
+ filter: FilterExpression | undefined,
263
+ layerIDs: string[],
264
+ ) => Promise<GeoJSON.FeatureCollection>;
265
+ queryRenderedFeaturesInRect: (
266
+ bbox: GeoJSON.BBox,
267
+ filter: FilterExpression | undefined,
268
+ layerIDs: string[],
269
+ ) => Promise<GeoJSON.FeatureCollection>;
270
+ setCamera: () => void;
271
+ takeSnap: (writeToDisk?: boolean) => Promise<string>;
272
+ getZoom: () => Promise<number>;
273
+ getCenter: () => Promise<GeoJSON.Position>;
274
+ setSourceVisibility: (
275
+ visible: boolean,
276
+ sourceId: string,
277
+ sourceLayerId?: string | null,
278
+ ) => void;
279
+ showAttribution: () => Promise<void>;
280
+ setNativeProps: (props: NativeProps) => void;
276
281
  }
277
282
 
278
283
  /**
279
284
  * MapView backed by MapLibre GL Native
280
285
  */
281
- class MapView extends NativeBridgeComponent(
282
- React.Component<MapViewProps, MapViewState>,
283
- NATIVE_MODULE_NAME,
284
- ) {
285
- static defaultProps = {
286
- localizeLabels: false,
287
- scrollEnabled: true,
288
- pitchEnabled: true,
289
- rotateEnabled: true,
290
- attributionEnabled: true,
291
- logoEnabled: false,
292
- surfaceView: false,
293
- regionWillChangeDebounceTime: 10,
294
- regionDidChangeDebounceTime: 500,
295
- };
296
-
297
- logger: Logger;
298
- _nativeRef?: RCTMLNMapViewRefType;
299
- _onDebouncedRegionWillChange: ReturnType<typeof debounce>;
300
- _onDebouncedRegionDidChange: ReturnType<typeof debounce>;
301
-
302
- constructor(props: MapViewProps) {
303
- super(props);
304
-
305
- this.logger = Logger.sharedInstance();
306
- this.logger.start();
307
-
308
- this.state = {
309
- isReady: false,
310
- region: null,
311
- width: 0,
312
- height: 0,
313
- isUserInteraction: false,
314
- };
315
-
316
- this._onPress = this._onPress.bind(this);
317
- this._onLongPress = this._onLongPress.bind(this);
318
- this._onChange = this._onChange.bind(this);
319
- this._onLayout = this._onLayout.bind(this);
320
-
321
- // debounced map change methods
322
- this._onDebouncedRegionWillChange = debounce(
323
- this._onRegionWillChange.bind(this),
324
- props.regionWillChangeDebounceTime,
325
- true,
326
- );
327
-
328
- this._onDebouncedRegionDidChange = debounce(
329
- this._onRegionDidChange.bind(this),
330
- props.regionDidChangeDebounceTime,
331
- );
332
- }
333
-
334
- componentDidMount(): void {
335
- this._setHandledMapChangedEvents(this.props);
336
- }
337
-
338
- componentWillUnmount(): void {
339
- this._onDebouncedRegionWillChange.clear();
340
- this._onDebouncedRegionDidChange.clear();
341
- this.logger.stop();
342
- }
343
-
344
- UNSAFE_componentWillReceiveProps(nextProps: MapViewProps): void {
345
- this._setHandledMapChangedEvents(nextProps);
346
- }
347
-
348
- _setHandledMapChangedEvents(props: MapViewProps): void {
349
- if (isAndroid()) {
350
- const events = [];
351
-
352
- if (props.onRegionWillChange) {
353
- events.push(MapLibreGL.EventTypes.RegionWillChange);
354
- }
355
- if (props.onRegionIsChanging) {
356
- events.push(MapLibreGL.EventTypes.RegionIsChanging);
357
- }
358
- if (props.onRegionDidChange) {
359
- events.push(MapLibreGL.EventTypes.RegionDidChange);
360
- }
361
- if (props.onUserLocationUpdate) {
362
- events.push(MapLibreGL.EventTypes.UserLocationUpdated);
363
- }
364
- if (props.onWillStartLoadingMap) {
365
- events.push(MapLibreGL.EventTypes.WillStartLoadingMap);
366
- }
367
- if (props.onDidFinishLoadingMap) {
368
- events.push(MapLibreGL.EventTypes.DidFinishLoadingMap);
369
- }
370
- if (props.onDidFailLoadingMap) {
371
- events.push(MapLibreGL.EventTypes.DidFailLoadingMap);
372
- }
373
- if (props.onWillStartRenderingFrame) {
374
- events.push(MapLibreGL.EventTypes.WillStartRenderingFrame);
375
- }
376
- if (props.onDidFinishRenderingFrame) {
377
- events.push(MapLibreGL.EventTypes.DidFinishRenderingFrame);
378
- }
379
- if (props.onDidFinishRenderingFrameFully) {
380
- events.push(MapLibreGL.EventTypes.DidFinishRenderingFrameFully);
381
- }
382
- if (props.onWillStartRenderingMap) {
383
- events.push(MapLibreGL.EventTypes.WillStartRenderingMap);
384
- }
385
- if (props.onDidFinishRenderingMap) {
386
- events.push(MapLibreGL.EventTypes.DidFinishRenderingMap);
387
- }
388
- if (props.onDidFinishRenderingMapFully) {
389
- events.push(MapLibreGL.EventTypes.DidFinishRenderingMapFully);
390
- }
391
- if (props.onDidFinishLoadingStyle) {
392
- events.push(MapLibreGL.EventTypes.DidFinishLoadingStyle);
393
- }
394
286
 
395
- this._runNativeCommand(
396
- 'setHandledMapChangedEvents',
397
- this._nativeRef,
398
- events,
287
+ const MapView = memo(
288
+ React.forwardRef<MapViewRef, MapViewProps>(
289
+ (
290
+ {
291
+ localizeLabels = false,
292
+ scrollEnabled = true,
293
+ pitchEnabled = true,
294
+ rotateEnabled = true,
295
+ attributionEnabled = true,
296
+ logoEnabled = false,
297
+ surfaceView = false,
298
+ regionWillChangeDebounceTime = 10,
299
+ regionDidChangeDebounceTime = 500,
300
+ ...props
301
+ }: MapViewProps,
302
+ ref,
303
+ ) => {
304
+ // * exposes the methods of the function component so we don't break projects that depend on calling this methods
305
+ useImperativeHandle(
306
+ ref,
307
+ (): MapViewRef => ({
308
+ /**
309
+ * Converts a geographic coordinate to a point in the given view’s coordinate system.
310
+ *
311
+ * @example
312
+ * const pointInView = await this._map.getPointInView([-37.817070, 144.949901]);
313
+ *
314
+ * @param {Array<Number>} coordinate - A point expressed in the map view's coordinate system.
315
+ * @return {Array}
316
+ */
317
+ getPointInView,
318
+ /**
319
+ * Converts a point in the given view’s coordinate system to a geographic coordinate.
320
+ *
321
+ * @example
322
+ * const coordinate = await this._map.getCoordinateFromView([100, 100]);
323
+ *
324
+ * @param {Array<Number>} point - A point expressed in the given view’s coordinate system.
325
+ * @return {Array}
326
+ */
327
+ getCoordinateFromView,
328
+ /**
329
+ * The coordinate bounds(ne, sw) visible in the users’s viewport.
330
+ *
331
+ * @example
332
+ * const visibleBounds = await this._map.getVisibleBounds();
333
+ *
334
+ * @return {Array}
335
+ */
336
+ getVisibleBounds,
337
+ /**
338
+ * Returns an array of rendered map features that intersect with a given point.
339
+ *
340
+ * @example
341
+ * this._map.queryRenderedFeaturesAtPoint([30, 40], ['==', 'type', 'Point'], ['id1', 'id2'])
342
+ *
343
+ * @param {Array<Number>} coordinate - A point expressed in the map view’s coordinate system.
344
+ * @param {Array=} filter - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.
345
+ * @param {Array=} layerIDs - A array of layer id's to filter the features by
346
+ * @return {GeoJSON.FeatureCollection}
347
+ */
348
+ queryRenderedFeaturesAtPoint,
349
+ /**
350
+ * Returns an array of rendered map features that intersect with the given rectangle,
351
+ * restricted to the given style layers and filtered by the given predicate.
352
+ *
353
+ * @example
354
+ * this._map.queryRenderedFeaturesInRect([30, 40, 20, 10], ['==', 'type', 'Point'], ['id1', 'id2'])
355
+ *
356
+ * @param {Array<Number>} bbox - A rectangle expressed in the map view’s coordinate system.
357
+ * @param {Array=} filter - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.
358
+ * @param {Array=} layerIDs - A array of layer id's to filter the features by
359
+ * @return {GeoJSON.FeatureCollection}
360
+ */
361
+ queryRenderedFeaturesInRect,
362
+ /**
363
+ * Map camera will perform updates based on provided config. Deprecated use Camera#setCamera.
364
+ */
365
+ setCamera,
366
+ /**
367
+ * Takes snapshot of map with current tiles and returns a URI to the image
368
+ * @param {Boolean} writeToDisk If true will create a temp file, otherwise it is in base64
369
+ * @return {String}
370
+ */
371
+ takeSnap,
372
+ /**
373
+ * Returns the current zoom of the map view.
374
+ *
375
+ * @example
376
+ * const zoom = await this._map.getZoom();
377
+ *
378
+ * @return {Number}
379
+ */
380
+ getZoom,
381
+ /**
382
+ * Returns the map's geographical centerpoint
383
+ *
384
+ * @example
385
+ * const center = await this._map.getCenter();
386
+ *
387
+ * @return {Array<Number>} Coordinates
388
+ */
389
+ getCenter,
390
+ /**
391
+ * Sets the visibility of all the layers referencing the specified `sourceLayerId` and/or `sourceId`
392
+ *
393
+ * @example
394
+ * await this._map.setSourceVisibility(false, 'composite', 'building')
395
+ *
396
+ * @param {boolean} visible - Visibility of the layers
397
+ * @param {String} sourceId - Identifier of the target source (e.g. 'composite')
398
+ * @param {String=} sourceLayerId - Identifier of the target source-layer (e.g. 'building')
399
+ */
400
+ setSourceVisibility,
401
+ /**
402
+ * Show the attribution and telemetry action sheet.
403
+ * If you implement a custom attribution button, you should add this action to the button.
404
+ */
405
+ showAttribution,
406
+ setNativeProps,
407
+ }),
399
408
  );
400
- }
401
- }
402
409
 
403
- /**
404
- * Converts a geographic coordinate to a point in the given view’s coordinate system.
405
- *
406
- * @example
407
- * const pointInView = await this._map.getPointInView([-37.817070, 144.949901]);
408
- *
409
- * @param {Array<Number>} coordinate - A point expressed in the map view's coordinate system.
410
- * @return {Array}
411
- */
412
- async getPointInView(coordinate: GeoJSON.Position): Promise<GeoJSON.Point> {
413
- const res: {pointInView: GeoJSON.Point} = await this._runNativeCommand(
414
- 'getPointInView',
415
- this._nativeRef,
416
- [coordinate],
417
- );
418
- return res.pointInView;
419
- }
410
+ const {_runNativeCommand, _runPendingNativeCommands, _onAndroidCallback} =
411
+ useNativeBridge(NATIVE_MODULE_NAME);
412
+ const logger = useRef<Logger>(Logger.sharedInstance());
413
+ // * start the logger before anyuseEffect
414
+ useOnce(() => {
415
+ logger.current.start();
416
+ });
417
+ const _nativeRef = useRef<RCTMLNMapViewRefType>();
418
+ const [isReady, setIsReady] = useState(false);
419
+
420
+ // Cleanups on unmount
421
+ useEffect(() => {
422
+ const currentLogger = logger.current;
423
+
424
+ return (): void => {
425
+ _onDebouncedRegionWillChange.clear();
426
+ _onDebouncedRegionDidChange.clear();
427
+ currentLogger.stop();
428
+ };
429
+ // eslint-disable-next-line react-hooks/exhaustive-deps
430
+ }, []);
431
+
432
+ // This will run on every render
433
+ // so similar to componentDidMount and UNSAFE_componentWillReceiveProps
434
+ useEffect(() => {
435
+ _setHandledMapChangedEvents(props);
436
+ }, [props]);
437
+
438
+ const _setHandledMapChangedEvents = (props: MapViewProps): void => {
439
+ if (isAndroid()) {
440
+ const events = [];
441
+
442
+ if (props.onRegionWillChange) {
443
+ events.push(MapLibreGL.EventTypes.RegionWillChange);
444
+ }
445
+ if (props.onRegionIsChanging) {
446
+ events.push(MapLibreGL.EventTypes.RegionIsChanging);
447
+ }
448
+ if (props.onRegionDidChange) {
449
+ events.push(MapLibreGL.EventTypes.RegionDidChange);
450
+ }
451
+ if (props.onUserLocationUpdate) {
452
+ events.push(MapLibreGL.EventTypes.UserLocationUpdated);
453
+ }
454
+ if (props.onWillStartLoadingMap) {
455
+ events.push(MapLibreGL.EventTypes.WillStartLoadingMap);
456
+ }
457
+ if (props.onDidFinishLoadingMap) {
458
+ events.push(MapLibreGL.EventTypes.DidFinishLoadingMap);
459
+ }
460
+ if (props.onDidFailLoadingMap) {
461
+ events.push(MapLibreGL.EventTypes.DidFailLoadingMap);
462
+ }
463
+ if (props.onWillStartRenderingFrame) {
464
+ events.push(MapLibreGL.EventTypes.WillStartRenderingFrame);
465
+ }
466
+ if (props.onDidFinishRenderingFrame) {
467
+ events.push(MapLibreGL.EventTypes.DidFinishRenderingFrame);
468
+ }
469
+ if (props.onDidFinishRenderingFrameFully) {
470
+ events.push(MapLibreGL.EventTypes.DidFinishRenderingFrameFully);
471
+ }
472
+ if (props.onWillStartRenderingMap) {
473
+ events.push(MapLibreGL.EventTypes.WillStartRenderingMap);
474
+ }
475
+ if (props.onDidFinishRenderingMap) {
476
+ events.push(MapLibreGL.EventTypes.DidFinishRenderingMap);
477
+ }
478
+ if (props.onDidFinishRenderingMapFully) {
479
+ events.push(MapLibreGL.EventTypes.DidFinishRenderingMapFully);
480
+ }
481
+ if (props.onDidFinishLoadingStyle) {
482
+ events.push(MapLibreGL.EventTypes.DidFinishLoadingStyle);
483
+ }
484
+
485
+ _runNativeCommand(
486
+ 'setHandledMapChangedEvents',
487
+ _nativeRef.current,
488
+ events,
489
+ );
490
+ }
491
+ };
420
492
 
421
- /**
422
- * Converts a point in the given view’s coordinate system to a geographic coordinate.
423
- *
424
- * @example
425
- * const coordinate = await this._map.getCoordinateFromView([100, 100]);
426
- *
427
- * @param {Array<Number>} point - A point expressed in the given view’s coordinate system.
428
- * @return {Array}
429
- */
430
- async getCoordinateFromView(point: number[]): Promise<GeoJSON.Position> {
431
- const res: {coordinateFromView: GeoJSON.Position} =
432
- await this._runNativeCommand('getCoordinateFromView', this._nativeRef, [
433
- point,
434
- ]);
435
- return res.coordinateFromView;
436
- }
493
+ const getPointInView = async (
494
+ coordinate: GeoJSON.Position,
495
+ ): Promise<GeoJSON.Point> => {
496
+ const res: {pointInView: GeoJSON.Point} = await _runNativeCommand(
497
+ 'getPointInView',
498
+ _nativeRef.current,
499
+ [coordinate],
500
+ );
501
+ return res.pointInView;
502
+ };
437
503
 
438
- /**
439
- * The coordinate bounds(ne, sw) visible in the users’s viewport.
440
- *
441
- * @example
442
- * const visibleBounds = await this._map.getVisibleBounds();
443
- *
444
- * @return {VisibleBounds}
445
- */
446
- async getVisibleBounds(): Promise<VisibleBounds> {
447
- const res: {visibleBounds: VisibleBounds} = await this._runNativeCommand(
448
- 'getVisibleBounds',
449
- this._nativeRef,
450
- );
451
- return res.visibleBounds;
452
- }
504
+ const getCoordinateFromView = async (
505
+ point: number[],
506
+ ): Promise<GeoJSON.Position> => {
507
+ const res: {coordinateFromView: GeoJSON.Position} =
508
+ await _runNativeCommand('getCoordinateFromView', _nativeRef.current, [
509
+ point,
510
+ ]);
511
+ return res.coordinateFromView;
512
+ };
453
513
 
454
- /**
455
- * Returns an array of rendered map features that intersect with a given point.
456
- *
457
- * @example
458
- * this._map.queryRenderedFeaturesAtPoint([30, 40], ['==', 'type', 'Point'], ['id1', 'id2'])
459
- *
460
- * @typedef {number} ScreenPointX
461
- * @typedef {number} ScreenPointY
462
- * @param {[ScreenPointX, ScreenPointY]} point - A point expressed in the map view’s coordinate system.
463
- * @param {Array=} filter - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.
464
- * @param {Array=} layerIDs - A array of layer id's to filter the features by
465
- * @return {GeoJSON.FeatureCollection}
466
- */
467
- async queryRenderedFeaturesAtPoint(
468
- point: [screenPointX: number, screenPointY: number],
469
- filter?: FilterExpression,
470
- layerIDs = [],
471
- ): Promise<GeoJSON.FeatureCollection> {
472
- if (!point || point.length < 2) {
473
- throw new Error(
474
- "Must pass in valid point in the map view's cooridnate system[x, y]",
475
- );
476
- }
514
+ const getVisibleBounds = async (): Promise<VisibleBounds> => {
515
+ const res: {visibleBounds: VisibleBounds} = await _runNativeCommand(
516
+ 'getVisibleBounds',
517
+ _nativeRef.current,
518
+ );
519
+ return res.visibleBounds;
520
+ };
477
521
 
478
- const res: {data: string | GeoJSON.FeatureCollection} =
479
- await this._runNativeCommand(
480
- 'queryRenderedFeaturesAtPoint',
481
- this._nativeRef,
482
- [point, getFilter(filter), layerIDs],
483
- );
522
+ const queryRenderedFeaturesAtPoint = async (
523
+ point: [screenPointX: number, screenPointY: number],
524
+ filter?: FilterExpression,
525
+ layerIDs: string[] = [],
526
+ ): Promise<GeoJSON.FeatureCollection> => {
527
+ if (!point || point.length < 2) {
528
+ throw new Error(
529
+ "Must pass in valid point in the map view's cooridnate system[x, y]",
530
+ );
531
+ }
484
532
 
485
- if (isAndroid()) {
486
- return JSON.parse(res.data as string);
487
- }
533
+ const res: {data: string | GeoJSON.FeatureCollection} =
534
+ await _runNativeCommand(
535
+ 'queryRenderedFeaturesAtPoint',
536
+ _nativeRef.current,
537
+ [point, getFilter(filter), layerIDs],
538
+ );
488
539
 
489
- return res.data as GeoJSON.FeatureCollection;
490
- }
540
+ if (isAndroid()) {
541
+ return JSON.parse(res.data as string);
542
+ }
491
543
 
492
- /**
493
- * Returns an array of rendered map features that intersect with the given rectangle,
494
- * restricted to the given style layers and filtered by the given predicate.
495
- *
496
- * @example
497
- * this._map.queryRenderedFeaturesInRect([30, 40, 20, 10], ['==', 'type', 'Point'], ['id1', 'id2'])
498
- *
499
- * @param {Array<Number>} bbox - A rectangle expressed in the map view’s coordinate system.
500
- * @param {Array=} filter - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.
501
- * @param {Array=} layerIDs - A array of layer id's to filter the features by
502
- * @return {GeoJSON.FeatureCollection}
503
- */
504
- async queryRenderedFeaturesInRect(
505
- bbox: GeoJSON.BBox,
506
- filter?: FilterExpression,
507
- layerIDs = [],
508
- ): Promise<GeoJSON.FeatureCollection> {
509
- if (!bbox || bbox.length !== 4) {
510
- throw new Error(
511
- 'Must pass in a valid bounding box[top, right, bottom, left]',
544
+ return res.data as GeoJSON.FeatureCollection;
545
+ };
546
+
547
+ const queryRenderedFeaturesInRect = async (
548
+ bbox: GeoJSON.BBox,
549
+ filter?: FilterExpression,
550
+ layerIDs: string[] = [],
551
+ ): Promise<GeoJSON.FeatureCollection> => {
552
+ if (!bbox || bbox.length !== 4) {
553
+ throw new Error(
554
+ 'Must pass in a valid bounding box[top, right, bottom, left]',
555
+ );
556
+ }
557
+ const res: {data: string | GeoJSON.FeatureCollection} =
558
+ await _runNativeCommand(
559
+ 'queryRenderedFeaturesInRect',
560
+ _nativeRef.current,
561
+ [bbox, getFilter(filter), layerIDs],
562
+ );
563
+
564
+ if (isAndroid()) {
565
+ return JSON.parse(res.data as string);
566
+ }
567
+
568
+ return res.data as GeoJSON.FeatureCollection;
569
+ };
570
+
571
+ const setCamera = (): void => {
572
+ console.warn(
573
+ 'MapView.setCamera is deprecated - please use Camera#setCamera',
574
+ );
575
+ };
576
+
577
+ const takeSnap = async (writeToDisk = false): Promise<string> => {
578
+ const res: {uri: string} = await _runNativeCommand(
579
+ 'takeSnap',
580
+ _nativeRef.current,
581
+ [writeToDisk],
582
+ );
583
+ return res.uri;
584
+ };
585
+
586
+ const getZoom = async (): Promise<number> => {
587
+ const res: {zoom: number} = await _runNativeCommand(
588
+ 'getZoom',
589
+ _nativeRef.current,
590
+ );
591
+ return res.zoom;
592
+ };
593
+
594
+ const getCenter = async (): Promise<GeoJSON.Position> => {
595
+ const res: {center: GeoJSON.Position} = await _runNativeCommand(
596
+ 'getCenter',
597
+ _nativeRef.current,
598
+ );
599
+ return res.center;
600
+ };
601
+
602
+ const setSourceVisibility = (
603
+ visible: boolean,
604
+ sourceId: string,
605
+ sourceLayerId: string | null = null,
606
+ ): void => {
607
+ _runNativeCommand('setSourceVisibility', _nativeRef.current, [
608
+ visible,
609
+ sourceId,
610
+ sourceLayerId,
611
+ ]);
612
+ };
613
+
614
+ const showAttribution = async (): Promise<void> => {
615
+ _runNativeCommand('showAttribution', _nativeRef.current);
616
+ };
617
+
618
+ const _onPress = (
619
+ e: NativeSyntheticEvent<{payload: GeoJSON.Feature}>,
620
+ ): void => {
621
+ if (isFunction(props.onPress)) {
622
+ props.onPress(e.nativeEvent.payload);
623
+ }
624
+ };
625
+
626
+ const _onLongPress = (
627
+ e: NativeSyntheticEvent<{payload: GeoJSON.Feature}>,
628
+ ): void => {
629
+ if (isFunction(props.onLongPress)) {
630
+ props.onLongPress(e.nativeEvent.payload);
631
+ }
632
+ };
633
+
634
+ const _onRegionWillChange = (
635
+ payload: GeoJSON.Feature<GeoJSON.Point, RegionPayload>,
636
+ ): void => {
637
+ if (isFunction(props.onRegionWillChange)) {
638
+ props.onRegionWillChange(payload);
639
+ }
640
+ };
641
+
642
+ const _onRegionDidChange = (
643
+ payload: GeoJSON.Feature<GeoJSON.Point, RegionPayload>,
644
+ ): void => {
645
+ if (isFunction(props.onRegionDidChange)) {
646
+ props.onRegionDidChange(payload);
647
+ }
648
+ };
649
+
650
+ const _onDebouncedRegionWillChange = useCallback(
651
+ debounce(_onRegionWillChange, regionWillChangeDebounceTime, {
652
+ immediate: true,
653
+ }),
654
+ [_onRegionWillChange],
512
655
  );
513
- }
514
- const res: {data: string | GeoJSON.FeatureCollection} =
515
- await this._runNativeCommand(
516
- 'queryRenderedFeaturesInRect',
517
- this._nativeRef,
518
- [bbox, getFilter(filter), layerIDs],
656
+
657
+ const _onDebouncedRegionDidChange = useCallback(
658
+ debounce(_onRegionDidChange, regionDidChangeDebounceTime),
659
+ [_onRegionDidChange],
519
660
  );
520
661
 
521
- if (isAndroid()) {
522
- return JSON.parse(res.data as string);
523
- }
662
+ const _onChange = (
663
+ e: NativeSyntheticEvent<{
664
+ type: string;
665
+ payload?: GeoJSON.Feature | Location;
666
+ }>,
667
+ ): void => {
668
+ const {type, payload} = e.nativeEvent;
669
+ let propName: CallableProps | undefined;
670
+
671
+ switch (type) {
672
+ case MapLibreGL.EventTypes.RegionWillChange:
673
+ if (
674
+ regionWillChangeDebounceTime &&
675
+ regionWillChangeDebounceTime > 0
676
+ ) {
677
+ if (payload) {
678
+ _onDebouncedRegionWillChange(
679
+ payload as GeoJSON.Feature<GeoJSON.Point, RegionPayload>,
680
+ );
681
+ }
682
+ } else {
683
+ propName = 'onRegionWillChange';
684
+ }
685
+ break;
686
+ case MapLibreGL.EventTypes.RegionIsChanging:
687
+ propName = 'onRegionIsChanging';
688
+ break;
689
+ case MapLibreGL.EventTypes.RegionDidChange:
690
+ if (
691
+ regionDidChangeDebounceTime &&
692
+ regionDidChangeDebounceTime > 0
693
+ ) {
694
+ if (payload) {
695
+ _onDebouncedRegionDidChange(
696
+ payload as GeoJSON.Feature<GeoJSON.Point, RegionPayload>,
697
+ );
698
+ }
699
+ } else {
700
+ propName = 'onRegionDidChange';
701
+ }
702
+ break;
703
+ case MapLibreGL.EventTypes.UserLocationUpdated:
704
+ propName = 'onUserLocationUpdate';
705
+ break;
706
+ case MapLibreGL.EventTypes.WillStartLoadingMap:
707
+ propName = 'onWillStartLoadingMap';
708
+ break;
709
+ case MapLibreGL.EventTypes.DidFinishLoadingMap:
710
+ propName = 'onDidFinishLoadingMap';
711
+ break;
712
+ case MapLibreGL.EventTypes.DidFailLoadingMap:
713
+ propName = 'onDidFailLoadingMap';
714
+ break;
715
+ case MapLibreGL.EventTypes.WillStartRenderingFrame:
716
+ propName = 'onWillStartRenderingFrame';
717
+ break;
718
+ case MapLibreGL.EventTypes.DidFinishRenderingFrame:
719
+ propName = 'onDidFinishRenderingFrame';
720
+ break;
721
+ case MapLibreGL.EventTypes.DidFinishRenderingFrameFully:
722
+ propName = 'onDidFinishRenderingFrameFully';
723
+ break;
724
+ case MapLibreGL.EventTypes.WillStartRenderingMap:
725
+ propName = 'onWillStartRenderingMap';
726
+ break;
727
+ case MapLibreGL.EventTypes.DidFinishRenderingMap:
728
+ propName = 'onDidFinishRenderingMap';
729
+ break;
730
+ case MapLibreGL.EventTypes.DidFinishRenderingMapFully:
731
+ propName = 'onDidFinishRenderingMapFully';
732
+ break;
733
+ case MapLibreGL.EventTypes.DidFinishLoadingStyle:
734
+ propName = 'onDidFinishLoadingStyle';
735
+ break;
736
+ default:
737
+ console.warn('Unhandled event callback type', type);
738
+ }
524
739
 
525
- return res.data as GeoJSON.FeatureCollection;
526
- }
740
+ if (propName) {
741
+ _handleOnChange(propName, payload);
742
+ }
743
+ };
527
744
 
528
- /**
529
- * Map camera will perform updates based on provided config. Deprecated use Camera#setCamera.
530
- */
531
- setCamera(): void {
532
- console.warn(
533
- 'MapView.setCamera is deprecated - please use Camera#setCamera',
534
- );
535
- }
745
+ const _onLayout = (): void => {
746
+ setIsReady(true);
747
+ };
536
748
 
537
- /**
538
- * Takes snapshot of map with current tiles and returns a URI to the image
539
- * @param {Boolean} writeToDisk If true will create a temp file, otherwise it is in base64
540
- * @return {String}
541
- */
542
- async takeSnap(writeToDisk = false): Promise<string> {
543
- const res: {uri: string} = await this._runNativeCommand(
544
- 'takeSnap',
545
- this._nativeRef,
546
- [writeToDisk],
547
- );
548
- return res.uri;
549
- }
749
+ const _handleOnChange = <T extends CallableProps>(
750
+ propName: T,
751
+ payload?: object,
752
+ ): void => {
753
+ const callable = props[propName] as (payload?: object) => void;
754
+ if (callable && isFunction(callable)) {
755
+ callable(payload);
756
+ }
757
+ };
550
758
 
551
- /**
552
- * Returns the current zoom of the map view.
553
- *
554
- * @example
555
- * const zoom = await this._map.getZoom();
556
- *
557
- * @return {Number}
558
- */
759
+ const contentInsetValue = useMemo(() => {
760
+ if (!props.contentInset) {
761
+ return;
762
+ }
559
763
 
560
- async getZoom(): Promise<number> {
561
- const res: {zoom: number} = await this._runNativeCommand(
562
- 'getZoom',
563
- this._nativeRef,
564
- );
565
- return res.zoom;
566
- }
764
+ if (!Array.isArray(props.contentInset)) {
765
+ return [props.contentInset];
766
+ }
567
767
 
568
- /**
569
- * Returns the map's geographical centerpoint
570
- *
571
- * @example
572
- * const center = await this._map.getCenter();
573
- *
574
- * @return {Array<Number>} Coordinates
575
- */
576
- async getCenter(): Promise<GeoJSON.Position> {
577
- const res: {center: GeoJSON.Position} = await this._runNativeCommand(
578
- 'getCenter',
579
- this._nativeRef,
580
- );
581
- return res.center;
582
- }
768
+ return props.contentInset;
769
+ }, [props.contentInset]);
583
770
 
584
- /**
585
- * Sets the visibility of all the layers referencing the specified `sourceLayerId` and/or `sourceId`
586
- *
587
- * @example
588
- * await this._map.setSourceVisibility(false, 'composite', 'building')
589
- *
590
- * @param {boolean} visible - Visibility of the layers
591
- * @param {String} sourceId - Identifier of the target source (e.g. 'composite')
592
- * @param {String=} sourceLayerId - Identifier of the target source-layer (e.g. 'building')
593
- */
594
- setSourceVisibility(
595
- visible: boolean,
596
- sourceId: string,
597
- sourceLayerId: string | null = null,
598
- ): void {
599
- this._runNativeCommand('setSourceVisibility', this._nativeRef, [
600
- visible,
601
- sourceId,
602
- sourceLayerId,
603
- ]);
604
- }
605
-
606
- /**
607
- * Show the attribution and telemetry action sheet.
608
- * If you implement a custom attribution button, you should add this action to the button.
609
- */
610
- async showAttribution(): Promise<void> {
611
- this._runNativeCommand('showAttribution', this._nativeRef);
612
- }
613
-
614
- _onPress(e: NativeSyntheticEvent<{payload: GeoJSON.Feature}>): void {
615
- if (isFunction(this.props.onPress)) {
616
- this.props.onPress(e.nativeEvent.payload);
617
- }
618
- }
619
-
620
- _onLongPress(e: NativeSyntheticEvent<{payload: GeoJSON.Feature}>): void {
621
- if (isFunction(this.props.onLongPress)) {
622
- this.props.onLongPress(e.nativeEvent.payload);
623
- }
624
- }
625
-
626
- _onRegionWillChange(
627
- payload: GeoJSON.Feature<GeoJSON.Point, RegionPayload>,
628
- ): void {
629
- if (isFunction(this.props.onRegionWillChange)) {
630
- this.props.onRegionWillChange(payload);
631
- }
632
- this.setState({isUserInteraction: payload.properties.isUserInteraction});
633
- }
634
-
635
- _onRegionDidChange(
636
- payload: GeoJSON.Feature<GeoJSON.Point, RegionPayload>,
637
- ): void {
638
- if (isFunction(this.props.onRegionDidChange)) {
639
- this.props.onRegionDidChange(payload);
640
- }
641
- this.setState({region: payload});
642
- }
643
-
644
- _onChange(
645
- e: NativeSyntheticEvent<{
646
- type: string;
647
- payload?: GeoJSON.Feature | Location;
648
- }>,
649
- ): void {
650
- const {regionWillChangeDebounceTime, regionDidChangeDebounceTime} =
651
- this.props;
652
- const {type, payload} = e.nativeEvent;
653
- let propName: CallableProps | undefined;
654
-
655
- switch (type) {
656
- case MapLibreGL.EventTypes.RegionWillChange:
657
- if (regionWillChangeDebounceTime && regionWillChangeDebounceTime > 0) {
658
- this._onDebouncedRegionWillChange(payload);
659
- } else {
660
- propName = 'onRegionWillChange';
771
+ const _setNativeRef = (nativeRef: RCTMLNMapViewRefType): void => {
772
+ _nativeRef.current = nativeRef;
773
+ _runPendingNativeCommands(nativeRef);
774
+ };
775
+
776
+ const setNativeProps = (props: NativeProps): void => {
777
+ if (_nativeRef.current) {
778
+ _nativeRef.current.setNativeProps(props);
661
779
  }
662
- break;
663
- case MapLibreGL.EventTypes.RegionIsChanging:
664
- propName = 'onRegionIsChanging';
665
- break;
666
- case MapLibreGL.EventTypes.RegionDidChange:
667
- if (regionDidChangeDebounceTime && regionDidChangeDebounceTime > 0) {
668
- this._onDebouncedRegionDidChange(payload);
669
- } else {
670
- propName = 'onRegionDidChange';
780
+ };
781
+
782
+ const _setStyleURL = (props: MapViewProps): void => {
783
+ // user set a styleURL, no need to alter props
784
+ if (props.styleURL) {
785
+ return;
671
786
  }
672
- break;
673
- case MapLibreGL.EventTypes.UserLocationUpdated:
674
- propName = 'onUserLocationUpdate';
675
- break;
676
- case MapLibreGL.EventTypes.WillStartLoadingMap:
677
- propName = 'onWillStartLoadingMap';
678
- break;
679
- case MapLibreGL.EventTypes.DidFinishLoadingMap:
680
- propName = 'onDidFinishLoadingMap';
681
- break;
682
- case MapLibreGL.EventTypes.DidFailLoadingMap:
683
- propName = 'onDidFailLoadingMap';
684
- break;
685
- case MapLibreGL.EventTypes.WillStartRenderingFrame:
686
- propName = 'onWillStartRenderingFrame';
687
- break;
688
- case MapLibreGL.EventTypes.DidFinishRenderingFrame:
689
- propName = 'onDidFinishRenderingFrame';
690
- break;
691
- case MapLibreGL.EventTypes.DidFinishRenderingFrameFully:
692
- propName = 'onDidFinishRenderingFrameFully';
693
- break;
694
- case MapLibreGL.EventTypes.WillStartRenderingMap:
695
- propName = 'onWillStartRenderingMap';
696
- break;
697
- case MapLibreGL.EventTypes.DidFinishRenderingMap:
698
- propName = 'onDidFinishRenderingMap';
699
- break;
700
- case MapLibreGL.EventTypes.DidFinishRenderingMapFully:
701
- propName = 'onDidFinishRenderingMapFully';
702
- break;
703
- case MapLibreGL.EventTypes.DidFinishLoadingStyle:
704
- propName = 'onDidFinishLoadingStyle';
705
- break;
706
- default:
707
- console.warn('Unhandled event callback type', type);
708
- }
709
-
710
- if (propName) {
711
- this._handleOnChange(propName, payload);
712
- }
713
- }
714
-
715
- _onLayout(e: LayoutChangeEvent): void {
716
- this.setState({
717
- isReady: true,
718
- width: e.nativeEvent.layout.width,
719
- height: e.nativeEvent.layout.height,
720
- });
721
- }
722
-
723
- _handleOnChange<T extends CallableProps>(
724
- propName: T,
725
- payload?: object,
726
- ): void {
727
- const callable = this.props[propName] as (payload?: object) => void;
728
- if (callable && isFunction(callable)) {
729
- callable(payload);
730
- }
731
- }
732
-
733
- _getContentInset(): number[] | undefined {
734
- if (!this.props.contentInset) {
735
- return;
736
- }
737
-
738
- if (!Array.isArray(this.props.contentInset)) {
739
- return [this.props.contentInset];
740
- }
741
-
742
- return this.props.contentInset;
743
- }
744
-
745
- _setNativeRef(nativeRef: RCTMLNMapViewRefType): void {
746
- this._nativeRef = nativeRef;
747
- super._runPendingNativeCommands(nativeRef);
748
- }
749
-
750
- setNativeProps(props: NativeProps): void {
751
- if (this._nativeRef) {
752
- this._nativeRef.setNativeProps(props);
753
- }
754
- }
755
-
756
- _setStyleURL(props: MapViewProps): void {
757
- // user set a styleURL, no need to alter props
758
- if (props.styleURL) {
759
- return;
760
- }
761
-
762
- // user set styleJSON pass it to styleURL
763
- if (props.styleJSON && !props.styleURL) {
764
- props.styleURL = props.styleJSON;
765
- }
766
-
767
- // user neither set styleJSON nor styleURL
768
- // set defaultStyleUrl
769
- if (!props.styleJSON || !props.styleURL) {
770
- props.styleURL = defaultStyleURL;
771
- }
772
- }
773
-
774
- render(): ReactElement {
775
- const props = {
776
- ...this.props,
777
- contentInset: this._getContentInset(),
778
- style: styles.matchParent,
779
- };
780
-
781
- this._setStyleURL(props);
782
-
783
- const callbacks = {
784
- ref: (ref: RCTMLNMapViewRefType) => this._setNativeRef(ref),
785
- onPress: this._onPress,
786
- onLongPress: this._onLongPress,
787
- onMapChange: this._onChange,
788
- onAndroidCallback: isAndroid() ? this._onAndroidCallback : undefined,
789
- };
790
-
791
- let mapView: ReactElement | null = null;
792
- if (isAndroid() && !this.props.surfaceView && this.state.isReady) {
793
- mapView = (
794
- <RCTMLNAndroidTextureMapView {...props} {...callbacks}>
795
- {this.props.children}
796
- </RCTMLNAndroidTextureMapView>
797
- );
798
- } else if (this.state.isReady) {
799
- mapView = (
800
- <RCTMLNMapView {...props} {...callbacks}>
801
- {this.props.children}
802
- </RCTMLNMapView>
787
+
788
+ // user set styleJSON pass it to styleURL
789
+ if (props.styleJSON && !props.styleURL) {
790
+ props.styleURL = props.styleJSON;
791
+ }
792
+
793
+ // user neither set styleJSON nor styleURL
794
+ // set defaultStyleUrl
795
+ if (!props.styleJSON || !props.styleURL) {
796
+ props.styleURL = defaultStyleURL;
797
+ }
798
+ };
799
+
800
+ const nativeProps = useMemo(() => {
801
+ return {
802
+ ...props,
803
+ localizeLabels,
804
+ scrollEnabled,
805
+ pitchEnabled,
806
+ rotateEnabled,
807
+ attributionEnabled,
808
+ logoEnabled,
809
+ surfaceView,
810
+ regionWillChangeDebounceTime,
811
+ regionDidChangeDebounceTime,
812
+ contentInsetValue,
813
+ style: styles.matchParent,
814
+ };
815
+ }, [
816
+ localizeLabels,
817
+ scrollEnabled,
818
+ pitchEnabled,
819
+ rotateEnabled,
820
+ attributionEnabled,
821
+ logoEnabled,
822
+ surfaceView,
823
+ regionWillChangeDebounceTime,
824
+ regionDidChangeDebounceTime,
825
+ contentInsetValue,
826
+ props,
827
+ contentInsetValue,
828
+ ]);
829
+
830
+ _setStyleURL(nativeProps);
831
+
832
+ const callbacks = {
833
+ ref: (ref: RCTMLNMapViewRefType): void => _setNativeRef(ref),
834
+ onPress: _onPress,
835
+ onLongPress: _onLongPress,
836
+ onMapChange: _onChange,
837
+ onAndroidCallback: isAndroid() ? _onAndroidCallback : undefined,
838
+ };
839
+
840
+ let mapView: ReactElement | null = null;
841
+ if (isAndroid() && !surfaceView && isReady) {
842
+ mapView = (
843
+ <RCTMLNAndroidTextureMapView {...nativeProps} {...callbacks}>
844
+ {props.children}
845
+ </RCTMLNAndroidTextureMapView>
846
+ );
847
+ } else if (isReady) {
848
+ mapView = (
849
+ <RCTMLNMapView {...nativeProps} {...callbacks}>
850
+ {props.children}
851
+ </RCTMLNMapView>
852
+ );
853
+ }
854
+
855
+ return (
856
+ <View
857
+ onLayout={_onLayout}
858
+ style={props.style}
859
+ testID={mapView ? undefined : props.testID}>
860
+ {mapView}
861
+ </View>
803
862
  );
804
- }
805
-
806
- return (
807
- <View
808
- onLayout={this._onLayout}
809
- style={this.props.style}
810
- testID={mapView ? undefined : this.props.testID}>
811
- {mapView}
812
- </View>
813
- );
814
- }
815
- }
863
+ },
864
+ ),
865
+ );
816
866
 
817
867
  type RCTMLNMapViewRefType = Component<NativeProps> & Readonly<NativeMethods>;
818
868
  const RCTMLNMapView = requireNativeComponent<NativeProps>(NATIVE_MODULE_NAME);