@maplibre/maplibre-react-native 9.1.0 → 10.0.0-alpha.2

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 (141) hide show
  1. package/.eslintrc.js +10 -2
  2. package/.husky/pre-commit +5 -0
  3. package/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
  4. package/.yarn/sdks/eslint/bin/eslint.js +20 -0
  5. package/.yarn/sdks/eslint/lib/api.js +20 -0
  6. package/.yarn/sdks/eslint/package.json +6 -0
  7. package/.yarn/sdks/integrations.yml +5 -0
  8. package/.yarn/sdks/prettier/index.js +20 -0
  9. package/.yarn/sdks/prettier/package.json +6 -0
  10. package/.yarn/sdks/typescript/bin/tsc +20 -0
  11. package/.yarn/sdks/typescript/bin/tsserver +20 -0
  12. package/.yarn/sdks/typescript/lib/tsc.js +20 -0
  13. package/.yarn/sdks/typescript/lib/tsserver.js +225 -0
  14. package/.yarn/sdks/typescript/lib/tsserverlibrary.js +225 -0
  15. package/.yarn/sdks/typescript/lib/typescript.js +20 -0
  16. package/.yarn/sdks/typescript/package.json +6 -0
  17. package/CHANGELOG.md +18 -0
  18. package/android/rctmgl/build.gradle +7 -7
  19. package/android/rctmgl/src/main/java/com/mapbox/rctmgl/location/LocationManager.java +2 -2
  20. package/android/rctmgl/src/main/java/com/mapbox/rctmgl/modules/RCTMGLOfflineModule.java +21 -26
  21. package/docs/Annotation.md +8 -9
  22. package/docs/BackgroundLayer.md +2 -10
  23. package/docs/Callout.md +5 -5
  24. package/docs/Camera.md +18 -47
  25. package/docs/CircleLayer.md +2 -10
  26. package/docs/FillExtrusionLayer.md +2 -10
  27. package/docs/FillLayer.md +2 -10
  28. package/docs/HeatmapLayer.md +2 -10
  29. package/docs/ImageSource.md +3 -2
  30. package/docs/Images.md +5 -3
  31. package/docs/Light.md +1 -1
  32. package/docs/LineLayer.md +2 -10
  33. package/docs/MapView.md +53 -37
  34. package/docs/MarkerView.md +4 -2
  35. package/docs/NativeUserLocation.md +2 -2
  36. package/docs/PointAnnotation.md +5 -8
  37. package/docs/RasterLayer.md +2 -10
  38. package/docs/RasterSource.md +3 -2
  39. package/docs/ShapeSource.md +12 -7
  40. package/docs/Style.md +1 -1
  41. package/docs/SymbolLayer.md +3 -10
  42. package/docs/UserLocation.md +8 -10
  43. package/docs/VectorSource.md +6 -5
  44. package/docs/coordinates.md +6 -0
  45. package/docs/docs.json +518 -1272
  46. package/docs/location.md +6 -0
  47. package/docs/snapshotManager.md +3 -3
  48. package/javascript/@types/assets.d.ts +4 -0
  49. package/javascript/MGLModule.ts +37 -0
  50. package/javascript/Maplibre.ts +65 -0
  51. package/javascript/components/AbstractLayer.tsx +107 -0
  52. package/javascript/components/AbstractSource.tsx +27 -0
  53. package/javascript/components/BackgroundLayer.tsx +43 -0
  54. package/javascript/components/{Callout.js → Callout.tsx} +67 -65
  55. package/javascript/components/{Camera.js → Camera.tsx} +266 -251
  56. package/javascript/components/CircleLayer.tsx +46 -0
  57. package/javascript/components/FillExtrusionLayer.tsx +47 -0
  58. package/javascript/components/FillLayer.tsx +41 -0
  59. package/javascript/components/{HeadingIndicator.js → HeadingIndicator.tsx} +8 -8
  60. package/javascript/components/HeatmapLayer.tsx +44 -0
  61. package/javascript/components/ImageSource.tsx +78 -0
  62. package/javascript/components/Images.tsx +134 -0
  63. package/javascript/components/Light.tsx +67 -0
  64. package/javascript/components/LineLayer.tsx +42 -0
  65. package/javascript/components/{MapView.js → MapView.tsx} +365 -354
  66. package/javascript/components/MarkerView.tsx +104 -0
  67. package/javascript/components/{NativeBridgeComponent.js → NativeBridgeComponent.tsx} +44 -13
  68. package/javascript/components/NativeUserLocation.tsx +33 -0
  69. package/javascript/components/PointAnnotation.tsx +221 -0
  70. package/javascript/components/RasterLayer.tsx +41 -0
  71. package/javascript/components/RasterSource.tsx +117 -0
  72. package/javascript/components/ShapeSource.tsx +383 -0
  73. package/javascript/components/{Style.js → Style.tsx} +129 -38
  74. package/javascript/components/SymbolLayer.tsx +72 -0
  75. package/javascript/components/{UserLocation.js → UserLocation.tsx} +111 -110
  76. package/javascript/components/VectorSource.tsx +207 -0
  77. package/javascript/components/annotations/Annotation.tsx +134 -0
  78. package/javascript/index.ts +4 -0
  79. package/javascript/modules/location/{locationManager.js → locationManager.ts} +71 -10
  80. package/javascript/modules/offline/{OfflineCreatePackOptions.js → OfflineCreatePackOptions.ts} +20 -4
  81. package/javascript/modules/offline/{OfflinePack.js → OfflinePack.ts} +23 -7
  82. package/javascript/modules/offline/{offlineManager.js → offlineManager.ts} +81 -24
  83. package/javascript/modules/snapshot/{SnapshotOptions.js → SnapshotOptions.ts} +43 -6
  84. package/javascript/modules/snapshot/{snapshotManager.js → snapshotManager.ts} +5 -5
  85. package/javascript/requestAndroidLocationPermissions.ts +29 -0
  86. package/javascript/types/BaseProps.ts +5 -0
  87. package/javascript/types/OnPressEvent.ts +13 -0
  88. package/javascript/types/index.ts +7 -0
  89. package/javascript/utils/BridgeValue.ts +90 -0
  90. package/javascript/utils/{Logger.js → Logger.ts} +37 -18
  91. package/javascript/utils/MaplibreStyles.d.ts +1486 -0
  92. package/javascript/utils/StyleValue.ts +49 -0
  93. package/javascript/utils/animated/AbstractAnimatedCoordinates.ts +134 -0
  94. package/javascript/utils/animated/AnimatedCoordinatesArray.ts +112 -0
  95. package/javascript/utils/animated/{AnimatedExtractCoordinateFromArray.js → AnimatedExtractCoordinateFromArray.ts} +5 -5
  96. package/javascript/utils/animated/{AnimatedPoint.js → AnimatedPoint.ts} +20 -12
  97. package/javascript/utils/animated/{AnimatedRouteCoordinatesArray.js → AnimatedRouteCoordinatesArray.ts} +39 -14
  98. package/javascript/utils/animated/{AnimatedShape.js → AnimatedShape.ts} +31 -10
  99. package/javascript/utils/{deprecation.js → deprecation.ts} +9 -6
  100. package/javascript/utils/filterUtils.ts +9 -0
  101. package/javascript/utils/geoUtils.ts +79 -0
  102. package/javascript/utils/{index.js → index.ts} +44 -24
  103. package/javascript/utils/styleMap.ts +264 -0
  104. package/package.json +35 -27
  105. package/plugin/build/withMapLibre.js +18 -3
  106. package/scripts/autogenHelpers/globals.js +1 -1
  107. package/scripts/autogenerate.js +14 -6
  108. package/scripts/download-style-spec.sh +1 -1
  109. package/scripts/templates/MaplibreStyles.ts.ejs +99 -0
  110. package/scripts/templates/index.d.ts.ejs +71 -42
  111. package/scripts/templates/{styleMap.js.ejs → styleMap.ts.ejs} +3 -33
  112. package/setup-jest.js +1 -10
  113. package/tsconfig.json +20 -61
  114. package/index.d.ts +0 -955
  115. package/javascript/components/AbstractLayer.js +0 -75
  116. package/javascript/components/AbstractSource.js +0 -15
  117. package/javascript/components/BackgroundLayer.js +0 -97
  118. package/javascript/components/CircleLayer.js +0 -101
  119. package/javascript/components/FillExtrusionLayer.js +0 -98
  120. package/javascript/components/FillLayer.js +0 -94
  121. package/javascript/components/HeatmapLayer.js +0 -99
  122. package/javascript/components/ImageSource.js +0 -82
  123. package/javascript/components/Images.js +0 -119
  124. package/javascript/components/Light.js +0 -47
  125. package/javascript/components/LineLayer.js +0 -94
  126. package/javascript/components/MarkerView.js +0 -87
  127. package/javascript/components/NativeUserLocation.js +0 -41
  128. package/javascript/components/PointAnnotation.js +0 -216
  129. package/javascript/components/RasterLayer.js +0 -95
  130. package/javascript/components/RasterSource.js +0 -124
  131. package/javascript/components/ShapeSource.js +0 -372
  132. package/javascript/components/SymbolLayer.js +0 -120
  133. package/javascript/components/VectorSource.js +0 -200
  134. package/javascript/components/annotations/Annotation.js +0 -122
  135. package/javascript/index.js +0 -149
  136. package/javascript/utils/BridgeValue.js +0 -81
  137. package/javascript/utils/animated/AnimatedCoordinatesArray.js +0 -191
  138. package/javascript/utils/filterUtils.js +0 -7
  139. package/javascript/utils/geoUtils.js +0 -73
  140. package/javascript/utils/styleMap.js +0 -1932
  141. /package/javascript/utils/animated/{Animated.js → Animated.ts} +0 -0
@@ -0,0 +1,72 @@
1
+ import {type SymbolLayerStyleProps} from '../utils/MaplibreStyles';
2
+ import BaseProps from '../types/BaseProps';
3
+
4
+ import AbstractLayer, {BaseLayerProps, NativeBaseProps} from './AbstractLayer';
5
+
6
+ import React, {ReactElement} from 'react';
7
+ import {View, NativeModules, requireNativeComponent} from 'react-native';
8
+
9
+ const MapLibreGL = NativeModules.MGLModule;
10
+
11
+ export const NATIVE_MODULE_NAME = 'RCTMGLSymbolLayer';
12
+
13
+ interface SymbolLayerProps extends BaseProps, BaseLayerProps {
14
+ /**
15
+ * Customizable style attributes
16
+ */
17
+ style?: SymbolLayerStyleProps;
18
+
19
+ /**
20
+ * @deprecated passed children used to create an image with id of symbol in style and also set the iconImageName property accordingly.
21
+ * This is now deprecated, use Image component instead.
22
+ */
23
+ children?: ReactElement | ReactElement[];
24
+ }
25
+
26
+ interface NativeProps extends Omit<SymbolLayerProps, 'style'>, NativeBaseProps {
27
+ snapshot: boolean;
28
+ }
29
+
30
+ /**
31
+ * SymbolLayer is a style layer that renders icon and text labels at points or along lines on the map.
32
+ */
33
+ class SymbolLayer extends AbstractLayer<SymbolLayerProps, NativeBaseProps> {
34
+ static defaultProps = {
35
+ sourceID: MapLibreGL.StyleSource.DefaultSourceID,
36
+ };
37
+
38
+ _shouldSnapshot(): boolean {
39
+ let isSnapshot = false;
40
+
41
+ if (React.Children.count(this.props.children) <= 0) {
42
+ return isSnapshot;
43
+ }
44
+
45
+ React.Children.forEach(this.props.children, child => {
46
+ if (child?.type === View) {
47
+ isSnapshot = true;
48
+ }
49
+ });
50
+
51
+ return isSnapshot;
52
+ }
53
+
54
+ render(): ReactElement {
55
+ const props = {
56
+ ...this.baseProps,
57
+ snapshot: this._shouldSnapshot(),
58
+ sourceLayerID: this.props.sourceLayerID,
59
+ };
60
+
61
+ return (
62
+ <RCTMGLSymbolLayer ref={this.setNativeLayer} {...props}>
63
+ {this.props.children}
64
+ </RCTMGLSymbolLayer>
65
+ );
66
+ }
67
+ }
68
+
69
+ const RCTMGLSymbolLayer =
70
+ requireNativeComponent<NativeProps>(NATIVE_MODULE_NAME);
71
+
72
+ export default SymbolLayer;
@@ -1,115 +1,122 @@
1
- import locationManager from '../modules/location/locationManager';
1
+ import locationManager, {Location} from '../modules/location/locationManager';
2
+ import {CircleLayerStyleProps} from '../utils/MaplibreStyles';
2
3
 
3
4
  import Annotation from './annotations/Annotation';
4
5
  import CircleLayer from './CircleLayer';
5
6
  import HeadingIndicator from './HeadingIndicator';
6
7
  import NativeUserLocation from './NativeUserLocation';
7
8
 
8
- import PropTypes from 'prop-types';
9
- import React from 'react';
9
+ import React, {ReactElement} from 'react';
10
10
 
11
11
  const mapboxBlue = 'rgba(51, 181, 229, 100)';
12
12
 
13
- const layerStyles = {
14
- normal: {
15
- pluse: {
16
- circleRadius: 15,
17
- circleColor: mapboxBlue,
18
- circleOpacity: 0.2,
19
- circlePitchAlignment: 'map',
20
- },
21
- background: {
22
- circleRadius: 9,
23
- circleColor: '#fff',
24
- circlePitchAlignment: 'map',
25
- },
26
- foreground: {
27
- circleRadius: 6,
28
- circleColor: mapboxBlue,
29
- circlePitchAlignment: 'map',
30
- },
13
+ const layerStyles: Record<string, CircleLayerStyleProps> = {
14
+ pluse: {
15
+ circleRadius: 15,
16
+ circleColor: mapboxBlue,
17
+ circleOpacity: 0.2,
18
+ circlePitchAlignment: 'map',
19
+ },
20
+ background: {
21
+ circleRadius: 9,
22
+ circleColor: '#fff',
23
+ circlePitchAlignment: 'map',
24
+ },
25
+ foreground: {
26
+ circleRadius: 6,
27
+ circleColor: mapboxBlue,
28
+ circlePitchAlignment: 'map',
31
29
  },
32
30
  };
33
31
 
34
- export const normalIcon = (showsUserHeadingIndicator, heading) => [
32
+ export const normalIcon = (
33
+ showsUserHeadingIndicator?: boolean,
34
+ heading?: number,
35
+ ): ReactElement[] => [
35
36
  <CircleLayer
36
37
  key="mapboxUserLocationPluseCircle"
37
38
  id="mapboxUserLocationPluseCircle"
38
- style={layerStyles.normal.pluse}
39
+ style={layerStyles.pluse}
39
40
  />,
40
41
  <CircleLayer
41
42
  key="mapboxUserLocationWhiteCircle"
42
43
  id="mapboxUserLocationWhiteCircle"
43
- style={layerStyles.normal.background}
44
+ style={layerStyles.background}
44
45
  />,
45
46
  <CircleLayer
46
47
  key="mapboxUserLocationBlueCicle"
47
48
  id="mapboxUserLocationBlueCicle"
48
49
  aboveLayerID="mapboxUserLocationWhiteCircle"
49
- style={layerStyles.normal.foreground}
50
+ style={layerStyles.foreground}
50
51
  />,
51
- ...(showsUserHeadingIndicator && heading !== null
52
- ? [HeadingIndicator(heading)]
52
+ ...(showsUserHeadingIndicator && heading
53
+ ? [HeadingIndicator({heading})]
53
54
  : []),
54
55
  ];
55
56
 
56
- class UserLocation extends React.Component {
57
- static propTypes = {
58
- /**
59
- * Whether location icon is animated between updates
60
- */
61
- animated: PropTypes.bool,
62
-
63
- /**
64
- * Which render mode to use.
65
- * Can either be `normal` or `native`
66
- */
67
- renderMode: PropTypes.oneOf(['normal', 'native']),
68
-
69
- /**
70
- * native/android only render mode
71
- *
72
- * - normal: just a circle
73
- * - compass: triangle with heading
74
- * - gps: large arrow
75
- *
76
- * @platform android
77
- */
78
- androidRenderMode: PropTypes.oneOf(['normal', 'compass', 'gps']),
79
-
80
- /**
81
- * Whether location icon is visible
82
- */
83
- visible: PropTypes.bool,
84
-
85
- /**
86
- * Callback that is triggered on location icon press
87
- */
88
- onPress: PropTypes.func,
89
-
90
- /**
91
- * Callback that is triggered on location update
92
- */
93
- onUpdate: PropTypes.func,
94
-
95
- /**
96
- * Show or hide small arrow which indicates direction the device is pointing relative to north.
97
- */
98
- showsUserHeadingIndicator: PropTypes.bool,
99
-
100
- /**
101
- * Minimum amount of movement before GPS location is updated in meters
102
- */
103
- minDisplacement: PropTypes.number,
104
-
105
- /**
106
- * Custom location icon of type mapbox-gl-native components
107
- *
108
- * NOTE: Forking maintainer does not understand the above comment.
109
- */
110
- children: PropTypes.any,
111
- };
57
+ interface UserLocationProps {
58
+ /**
59
+ * Whether location icon is animated between updates
60
+ */
61
+ animated?: boolean;
62
+ /**
63
+ * Which render mode to use.
64
+ * Can either be `normal` or `native`
65
+ */
66
+ renderMode?: 'normal' | 'native';
67
+ /**
68
+ * native/android only render mode
69
+ *
70
+ * - normal: just a circle
71
+ * - compass: triangle with heading
72
+ * - gps: large arrow
73
+ *
74
+ * @platform android
75
+ */
76
+ androidRenderMode?: 'normal' | 'compass' | 'gps';
77
+ /**
78
+ * Whether location icon is visible
79
+ */
80
+ visible?: boolean;
81
+ /**
82
+ * Callback that is triggered on location icon press
83
+ */
84
+ onPress?(): void;
85
+ /**
86
+ * Callback that is triggered on location update
87
+ */
88
+ onUpdate?(location: Location): void;
89
+ /**
90
+ * Show or hide small arrow which indicates direction the device is pointing relative to north.
91
+ */
92
+ showsUserHeadingIndicator?: boolean;
93
+ /**
94
+ * Minimum amount of movement before GPS location is updated in meters
95
+ */
96
+ minDisplacement?: number;
97
+ /**
98
+ * Custom location icon of type mapbox-gl-native components
99
+ *
100
+ * NOTE: Forking maintainer does not understand the above comment.
101
+ */
102
+ children?: ReactElement | ReactElement[];
103
+ }
104
+
105
+ interface UserLocationState {
106
+ shouldShowUserLocation: boolean;
107
+ coordinates?: number[];
108
+ heading?: number;
109
+ }
110
+
111
+ export enum UserLocationRenderMode {
112
+ Native = 'native',
113
+ Normal = 'normal',
114
+ }
112
115
 
116
+ class UserLocation extends React.Component<
117
+ UserLocationProps,
118
+ UserLocationState
119
+ > {
113
120
  static defaultProps = {
114
121
  animated: true,
115
122
  visible: true,
@@ -118,18 +125,11 @@ class UserLocation extends React.Component {
118
125
  renderMode: 'normal',
119
126
  };
120
127
 
121
- static RenderMode = {
122
- Native: 'native',
123
- Normal: 'normal',
124
- };
125
-
126
- constructor(props) {
128
+ constructor(props: UserLocationProps) {
127
129
  super(props);
128
130
 
129
131
  this.state = {
130
132
  shouldShowUserLocation: false,
131
- coordinates: null,
132
- heading: null,
133
133
  };
134
134
 
135
135
  this._onLocationUpdate = this._onLocationUpdate.bind(this);
@@ -137,35 +137,36 @@ class UserLocation extends React.Component {
137
137
 
138
138
  // required as #setLocationManager attempts to setState
139
139
  // after component unmount
140
- _isMounted = null;
140
+ _isMounted: boolean | null = null;
141
141
 
142
+ renderMode: UserLocationRenderMode | undefined;
142
143
  locationManagerRunning = false;
143
144
 
144
- async componentDidMount() {
145
+ async componentDidMount(): Promise<void> {
145
146
  this._isMounted = true;
146
147
 
147
148
  await this.setLocationManager({
148
149
  running: this.needsLocationManagerRunning(),
149
150
  });
150
151
 
151
- if (this.renderMode === UserLocation.RenderMode.Native) {
152
+ if (this.renderMode === UserLocationRenderMode.Native) {
152
153
  return;
153
154
  }
154
155
 
155
- locationManager.setMinDisplacement(this.props.minDisplacement);
156
+ locationManager.setMinDisplacement(this.props.minDisplacement ?? 0);
156
157
  }
157
158
 
158
- async componentDidUpdate(prevProps) {
159
+ async componentDidUpdate(prevProps: UserLocationProps): Promise<void> {
159
160
  await this.setLocationManager({
160
161
  running: this.needsLocationManagerRunning(),
161
162
  });
162
163
 
163
164
  if (this.props.minDisplacement !== prevProps.minDisplacement) {
164
- locationManager.setMinDisplacement(this.props.minDisplacement);
165
+ locationManager.setMinDisplacement(this.props.minDisplacement ?? 0);
165
166
  }
166
167
  }
167
168
 
168
- async componentWillUnmount() {
169
+ async componentWillUnmount(): Promise<void> {
169
170
  this._isMounted = false;
170
171
  await this.setLocationManager({running: false});
171
172
  }
@@ -180,7 +181,7 @@ class UserLocation extends React.Component {
180
181
  * @param {Object} running - Object with key `running` and `boolean` value
181
182
  * @return {Promise<void>}
182
183
  */
183
- async setLocationManager({running}) {
184
+ async setLocationManager({running}: {running: boolean}): Promise<void> {
184
185
  if (this.locationManagerRunning !== running) {
185
186
  this.locationManagerRunning = running;
186
187
  if (running) {
@@ -199,24 +200,24 @@ class UserLocation extends React.Component {
199
200
  *
200
201
  * @return {boolean}
201
202
  */
202
- needsLocationManagerRunning() {
203
- return (
203
+ needsLocationManagerRunning(): boolean {
204
+ return !!(
204
205
  !!this.props.onUpdate ||
205
- (this.props.renderMode === UserLocation.RenderMode.Normal &&
206
+ (this.props.renderMode === UserLocationRenderMode.Normal &&
206
207
  this.props.visible)
207
208
  );
208
209
  }
209
210
 
210
- _onLocationUpdate(location) {
211
+ _onLocationUpdate(location: Location | null): void {
211
212
  if (!this._isMounted || !location) {
212
213
  return;
213
214
  }
214
- let coordinates = null;
215
- let heading = null;
215
+ let coordinates;
216
+ let heading;
216
217
 
217
218
  if (location && location.coords) {
218
219
  const {longitude, latitude} = location.coords;
219
- ({heading} = location.coords);
220
+ heading = location.coords.heading;
220
221
  coordinates = [longitude, latitude];
221
222
  }
222
223
 
@@ -230,17 +231,17 @@ class UserLocation extends React.Component {
230
231
  }
231
232
  }
232
233
 
233
- _renderNative() {
234
+ _renderNative(): ReactElement {
234
235
  const {androidRenderMode, showsUserHeadingIndicator} = this.props;
235
236
 
236
- let props = {
237
+ const props = {
237
238
  androidRenderMode,
238
239
  iosShowsUserHeadingIndicator: showsUserHeadingIndicator,
239
240
  };
240
241
  return <NativeUserLocation {...props} />;
241
242
  }
242
243
 
243
- render() {
244
+ render(): ReactElement | null {
244
245
  const {heading, coordinates} = this.state;
245
246
  const {children, visible, showsUserHeadingIndicator, onPress, animated} =
246
247
  this.props;
@@ -249,7 +250,7 @@ class UserLocation extends React.Component {
249
250
  return null;
250
251
  }
251
252
 
252
- if (this.props.renderMode === UserLocation.RenderMode.Native) {
253
+ if (this.props.renderMode === UserLocationRenderMode.Native) {
253
254
  return this._renderNative();
254
255
  }
255
256
 
@@ -0,0 +1,207 @@
1
+ import {FilterExpression} from '../utils/MaplibreStyles';
2
+ import {cloneReactChildrenWithProps, isFunction, isAndroid} from '../utils';
3
+ import {getFilter} from '../utils/filterUtils';
4
+ import {copyPropertiesAsDeprecated} from '../utils/deprecation';
5
+ import BaseProps from '../types/BaseProps';
6
+ import OnPressEvent from '../types/OnPressEvent';
7
+
8
+ import AbstractSource from './AbstractSource';
9
+ import NativeBridgeComponent from './NativeBridgeComponent';
10
+
11
+ import React, {Component, ReactNode} from 'react';
12
+ import {
13
+ NativeMethods,
14
+ NativeModules,
15
+ NativeSyntheticEvent,
16
+ requireNativeComponent,
17
+ } from 'react-native';
18
+ import {featureCollection} from '@turf/helpers';
19
+
20
+ const MapLibreGL = NativeModules.MGLModule;
21
+
22
+ export const NATIVE_MODULE_NAME = 'RCTMGLVectorSource';
23
+
24
+ interface VectorSourceProps extends BaseProps {
25
+ /**
26
+ * A string that uniquely identifies the source.
27
+ */
28
+ id: string;
29
+ /**
30
+ * A URL to a TileJSON configuration file describing the source’s contents and other metadata.
31
+ */
32
+ url?: string;
33
+ /**
34
+ * An array of tile URL templates. If multiple endpoints are specified, clients may use any combination of endpoints.
35
+ * Example: https://example.com/vector-tiles/{z}/{x}/{y}.pbf
36
+ */
37
+ tileUrlTemplates?: string[];
38
+ /**
39
+ * An unsigned integer that specifies the minimum zoom level at which to display tiles from the source.
40
+ * The value should be between 0 and 22, inclusive, and less than
41
+ * maxZoomLevel, if specified. The default value for this option is 0.
42
+ */
43
+ minZoomLevel?: number;
44
+ /**
45
+ * An unsigned integer that specifies the maximum zoom level at which to display tiles from the source.
46
+ * The value should be between 0 and 22, inclusive, and less than
47
+ * minZoomLevel, if specified. The default value for this option is 22.
48
+ */
49
+ maxZoomLevel?: number;
50
+ /**
51
+ * Influences the y direction of the tile coordinates. (tms inverts y axis)
52
+ */
53
+ tms?: boolean;
54
+ /**
55
+ * An HTML or literal text string defining the buttons to be displayed in an action sheet when the
56
+ * source is part of a map view’s style and the map view’s attribution button is pressed.
57
+ */
58
+ attribution?: string;
59
+ /**
60
+ * Source press listener, gets called when a user presses one of the children layers only
61
+ * if that layer has a higher z-index than another source layers
62
+ *
63
+ * @param {Object} event
64
+ * @param {Object[]} event.features - the geojson features that have hit by the press (might be multiple)
65
+ * @param {Object} event.coordinates - the coordinates of the click
66
+ * @param {Object} event.point - the point of the click
67
+ */
68
+ onPress?: (event: OnPressEvent) => void;
69
+ /**
70
+ * Overrides the default touch hitbox(44x44 pixels) for the source layers
71
+ */
72
+ hitbox?: {
73
+ /**
74
+ * `width` of hitbox
75
+ */
76
+ width: number;
77
+ /**
78
+ * `height` of hitbox
79
+ */
80
+ height: number;
81
+ };
82
+
83
+ children?: React.ReactElement | React.ReactElement[];
84
+ }
85
+
86
+ type NativeProps = VectorSourceProps;
87
+
88
+ /**
89
+ * VectorSource is a map content source that supplies tiled vector data in Mapbox Vector Tile format to be shown on the map.
90
+ * The location of and metadata about the tiles are defined either by an option dictionary or by an external file that conforms to the TileJSON specification.
91
+ */
92
+ class VectorSource extends NativeBridgeComponent(
93
+ AbstractSource<VectorSourceProps, NativeProps>,
94
+ NATIVE_MODULE_NAME,
95
+ ) {
96
+ static defaultProps = {
97
+ id: MapLibreGL.StyleSource.DefaultSourceID,
98
+ };
99
+
100
+ constructor(props: VectorSourceProps) {
101
+ super(props);
102
+ }
103
+
104
+ _setNativeRef(
105
+ nativeRef: (Component<NativeProps> & Readonly<NativeMethods>) | null,
106
+ ): void {
107
+ if (nativeRef) {
108
+ this.setNativeRef(nativeRef);
109
+ super._runPendingNativeCommands(nativeRef);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Returns all features that match the query parameters regardless of whether or not the feature is
115
+ * currently rendered on the map. The domain of the query includes all currently-loaded vector tiles
116
+ * and GeoJSON source tiles. This function does not check tiles outside of the visible viewport.
117
+ *
118
+ * @example
119
+ * vectorSource.features(['id1', 'id2'])
120
+ *
121
+ * @param {Array=} layerIDs - 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.
122
+ * @param {Array=} filter - an optional filter statement to filter the returned Features.
123
+ * @return {GeoJSON.FeatureCollection}
124
+ */
125
+ async features(
126
+ layerIDs = [],
127
+ filter?: FilterExpression,
128
+ ): Promise<GeoJSON.FeatureCollection> {
129
+ if (!this._nativeRef) {
130
+ return featureCollection([]);
131
+ }
132
+ const res: {data: string | GeoJSON.FeatureCollection} =
133
+ await this._runNativeCommand('features', this._nativeRef, [
134
+ [[layerIDs, getFilter(filter)]],
135
+ ]);
136
+
137
+ if (isAndroid()) {
138
+ return JSON.parse(res?.data as string);
139
+ }
140
+
141
+ return res.data as GeoJSON.FeatureCollection;
142
+ }
143
+
144
+ onPress(event: NativeSyntheticEvent<{payload: OnPressEvent}>): void {
145
+ const {onPress} = this.props;
146
+
147
+ if (!onPress) {
148
+ return;
149
+ }
150
+ const {
151
+ nativeEvent: {
152
+ payload: {features, coordinates, point},
153
+ },
154
+ } = event;
155
+ let newEvent = {
156
+ features,
157
+ coordinates,
158
+ point,
159
+ };
160
+ newEvent = copyPropertiesAsDeprecated(
161
+ event,
162
+ newEvent,
163
+ (key: string) => {
164
+ console.warn(
165
+ `event.${key} is deprecated on VectorSource#onPress, please use event.features`,
166
+ );
167
+ },
168
+ {
169
+ nativeEvent: (origNativeEvent: OnPressEvent) => ({
170
+ ...origNativeEvent,
171
+ payload: features[0],
172
+ }),
173
+ },
174
+ );
175
+
176
+ onPress(newEvent);
177
+ }
178
+
179
+ render(): ReactNode {
180
+ const props = {
181
+ id: this.props.id,
182
+ url: this.props.url,
183
+ tileUrlTemplates: this.props.tileUrlTemplates,
184
+ minZoomLevel: this.props.minZoomLevel,
185
+ maxZoomLevel: this.props.maxZoomLevel,
186
+ tms: this.props.tms,
187
+ attribution: this.props.attribution,
188
+ hitbox: this.props.hitbox,
189
+ hasPressListener: isFunction(this.props.onPress),
190
+ onMapboxVectorSourcePress: this.onPress.bind(this),
191
+ onPress: undefined,
192
+ onAndroidCallback: isAndroid() ? this._onAndroidCallback : undefined,
193
+ };
194
+ return (
195
+ <RCTMGLVectorSource ref={this.setNativeRef} {...props}>
196
+ {cloneReactChildrenWithProps(this.props.children, {
197
+ sourceID: this.props.id,
198
+ })}
199
+ </RCTMGLVectorSource>
200
+ );
201
+ }
202
+ }
203
+
204
+ const RCTMGLVectorSource =
205
+ requireNativeComponent<VectorSourceProps>(NATIVE_MODULE_NAME);
206
+
207
+ export default VectorSource;