@rnmapbox/maps 10.3.0-beta.1 → 10.3.0

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 (86) hide show
  1. package/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXMarkerViewContent.kt +55 -0
  2. package/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXMarkerViewContentManager.kt +7 -2
  3. package/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXMarkerViewManager.kt +0 -2
  4. package/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXPointAnnotation.kt +14 -1
  5. package/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXPointAnnotationManager.kt +11 -0
  6. package/android/src/main/java/com/rnmapbox/rnmbx/components/location/RNMBXNativeUserLocationManager.kt +25 -24
  7. package/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/NativeMapViewModule.kt +3 -2
  8. package/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt +57 -39
  9. package/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt +0 -9
  10. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleFactory.kt +60 -0
  11. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/atmosphere/RNMBXAtmosphere.kt +4 -4
  12. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/atmosphere/RNMBXAtmosphereManager.kt +2 -1
  13. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/light/RNMBXLightManager.kt +2 -1
  14. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt +2 -6
  15. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/terrain/RNMBXTerrainManager.kt +2 -1
  16. package/android/src/main/java/com/rnmapbox/rnmbx/events/FeatureClickEvent.java +5 -6
  17. package/android/src/main/java/com/rnmapbox/rnmbx/modules/RNMBXModule.kt +1 -0
  18. package/android/src/main/java/com/rnmapbox/rnmbx/modules/RNMBXSnapshotModule.kt +56 -18
  19. package/android/src/main/java/com/rnmapbox/rnmbx/utils/ConvertUtils.kt +0 -30
  20. package/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/Dynamic.kt +3 -1
  21. package/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableArray.kt +16 -14
  22. package/ios/RNMBX/RNMBXBackgroundLayer.swift +1 -1
  23. package/ios/RNMBX/RNMBXCalloutComponentView.mm +10 -0
  24. package/ios/RNMBX/RNMBXCircleLayer.swift +1 -1
  25. package/ios/RNMBX/RNMBXFillExtrusionLayer.swift +1 -1
  26. package/ios/RNMBX/RNMBXFillLayer.swift +1 -1
  27. package/ios/RNMBX/RNMBXHeatmapLayer.swift +1 -1
  28. package/ios/RNMBX/RNMBXHillshadeLayer.swift +1 -1
  29. package/ios/RNMBX/RNMBXLayer.swift +2 -2
  30. package/ios/RNMBX/RNMBXLineLayer.swift +1 -1
  31. package/ios/RNMBX/RNMBXMapView.swift +18 -1
  32. package/ios/RNMBX/RNMBXMapViewComponentView.mm +3 -0
  33. package/ios/RNMBX/RNMBXMapViewModule.mm +1 -1
  34. package/ios/RNMBX/RNMBXModelLayer.swift +1 -1
  35. package/ios/RNMBX/RNMBXModule.swift +1 -0
  36. package/ios/RNMBX/RNMBXPointAnnotation.swift +25 -3
  37. package/ios/RNMBX/RNMBXPointAnnotationComponentView.mm +1 -0
  38. package/ios/RNMBX/RNMBXRasterLayer.swift +1 -1
  39. package/ios/RNMBX/RNMBXRasterParticleLayer.swift +1 -1
  40. package/ios/RNMBX/RNMBXSkyLayer.swift +1 -1
  41. package/ios/RNMBX/RNMBXSnapshotModule.swift +3 -1
  42. package/ios/RNMBX/RNMBXStyle.swift +36 -0
  43. package/ios/RNMBX/RNMBXSymbolLayer.swift +1 -1
  44. package/lib/module/Mapbox.native.js.map +1 -1
  45. package/lib/module/components/MapView.js +95 -113
  46. package/lib/module/components/MapView.js.map +1 -1
  47. package/lib/module/components/MarkerView.js +93 -76
  48. package/lib/module/components/MarkerView.js.map +1 -1
  49. package/lib/module/components/UserLocation.js +2 -1
  50. package/lib/module/components/UserLocation.js.map +1 -1
  51. package/lib/module/modules/offline/offlineManager.js +2 -12
  52. package/lib/module/modules/offline/offlineManager.js.map +1 -1
  53. package/lib/module/specs/RNMBXMarkerViewContentNativeComponent.ts +13 -1
  54. package/lib/module/specs/RNMBXPointAnnotationNativeComponent.ts +1 -0
  55. package/lib/module/utils/styleMap.js +4 -0
  56. package/lib/module/utils/styleMap.js.map +1 -1
  57. package/lib/typescript/scripts/autogenHelpers/generateCodeWithEjs.d.mts.map +1 -1
  58. package/lib/typescript/src/Mapbox.native.d.ts +1 -1
  59. package/lib/typescript/src/Mapbox.native.d.ts.map +1 -1
  60. package/lib/typescript/src/components/Camera.d.ts +2 -2
  61. package/lib/typescript/src/components/Camera.d.ts.map +1 -1
  62. package/lib/typescript/src/components/MapView.d.ts +53 -41
  63. package/lib/typescript/src/components/MapView.d.ts.map +1 -1
  64. package/lib/typescript/src/components/MarkerView.d.ts +10 -17
  65. package/lib/typescript/src/components/MarkerView.d.ts.map +1 -1
  66. package/lib/typescript/src/components/UserLocation.d.ts.map +1 -1
  67. package/lib/typescript/src/modules/offline/offlineManager.d.ts.map +1 -1
  68. package/lib/typescript/src/specs/RNMBXMarkerViewContentNativeComponent.d.ts +6 -0
  69. package/lib/typescript/src/specs/RNMBXMarkerViewContentNativeComponent.d.ts.map +1 -1
  70. package/lib/typescript/src/specs/RNMBXPointAnnotationNativeComponent.d.ts +1 -0
  71. package/lib/typescript/src/specs/RNMBXPointAnnotationNativeComponent.d.ts.map +1 -1
  72. package/lib/typescript/src/utils/MapboxStyles.d.ts +16 -0
  73. package/lib/typescript/src/utils/MapboxStyles.d.ts.map +1 -1
  74. package/lib/typescript/src/utils/styleMap.d.ts.map +1 -1
  75. package/package.json +1 -1
  76. package/setup-jest.js +1 -1
  77. package/src/Mapbox.native.ts +5 -1
  78. package/src/components/Camera.tsx +2 -2
  79. package/src/components/MapView.tsx +137 -154
  80. package/src/components/MarkerView.tsx +118 -95
  81. package/src/components/UserLocation.tsx +3 -2
  82. package/src/modules/offline/offlineManager.ts +2 -14
  83. package/src/specs/RNMBXMarkerViewContentNativeComponent.ts +13 -1
  84. package/src/specs/RNMBXPointAnnotationNativeComponent.ts +1 -0
  85. package/src/utils/MapboxStyles.ts +18 -0
  86. package/src/utils/styleMap.ts +4 -0
@@ -1,15 +1,19 @@
1
- import React from 'react';
2
- import { NativeModules, Platform, type ViewProps } from 'react-native';
1
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
2
+ import {
3
+ PixelRatio,
4
+ StyleSheet,
5
+ type NativeSyntheticEvent,
6
+ type ViewProps,
7
+ } from 'react-native';
3
8
 
4
9
  import RNMBXMakerViewContentComponent from '../specs/RNMBXMarkerViewContentNativeComponent';
5
10
  import NativeMarkerViewComponent from '../specs/RNMBXMarkerViewNativeComponent';
6
11
  import { type Position } from '../types/Position';
7
- import { toJSONString } from '../utils';
8
- import { makePoint } from '../utils/geoUtils';
9
12
 
10
- import PointAnnotation from './PointAnnotation';
13
+ // Device pixel ratio is constant for the lifetime of the app.
14
+ const PIXEL_RATIO = PixelRatio.get();
11
15
 
12
- const Mapbox = NativeModules.RNMBXModule;
16
+ const DEFAULT_ANCHOR = { x: 0.5, y: 0.5 };
13
17
 
14
18
  type Props = ViewProps & {
15
19
  /**
@@ -21,29 +25,28 @@ type Props = ViewProps & {
21
25
  * Any coordinate between (0, 0) and (1, 1), where (0, 0) is the top-left corner of
22
26
  * the view, and (1, 1) is the bottom-right corner. Defaults to the center at (0.5, 0.5).
23
27
  */
24
- anchor: {
28
+ anchor?: {
25
29
  x: number;
26
30
  y: number;
27
31
  };
28
32
 
29
33
  /**
30
- * @v10
31
- *
32
34
  * Whether or not nearby markers on the map should all be displayed. If false, adjacent
33
35
  * markers will 'collapse' and only one will be shown. Defaults to false.
34
36
  */
35
- allowOverlap: boolean;
37
+ allowOverlap?: boolean;
36
38
 
37
39
  /**
38
40
  * Whether or not nearby markers on the map should be hidden if close to a
39
41
  * UserLocation puck. Defaults to false.
40
42
  */
41
- allowOverlapWithPuck: boolean;
43
+ allowOverlapWithPuck?: boolean;
42
44
 
43
- isSelected: boolean;
45
+ isSelected?: boolean;
44
46
 
45
47
  /**
46
- * One or more valid React Native views.
48
+ * One or more valid React Native views. You can use Pressable, TouchableOpacity,
49
+ * etc. directly as children — onPress and touch feedback work correctly.
47
50
  */
48
51
  children: React.ReactElement;
49
52
  };
@@ -58,93 +61,113 @@ type Props = ViewProps & {
58
61
  * This is implemented with view annotations on [Android](https://docs.mapbox.com/android/maps/guides/annotations/view-annotations/)
59
62
  * and [iOS](https://docs.mapbox.com/ios/maps/guides/annotations/view-annotations).
60
63
  *
61
- * This component has no dedicated `onPress` method. Instead, you should handle gestures
62
- * with the React views passed in as `children`.
64
+ * This component has no dedicated `onPress` method. Instead, handle gestures
65
+ * with the React views passed in as `children` — Pressable, TouchableOpacity,
66
+ * etc. all work including their visual feedback (opacity, scale, etc.).
63
67
  */
64
- class MarkerView extends React.PureComponent<Props> {
65
- static defaultProps: Partial<Props> = {
66
- anchor: { x: 0.5, y: 0.5 },
67
- allowOverlap: false,
68
- allowOverlapWithPuck: false,
69
- isSelected: false,
70
- };
71
-
72
- static lastId = 0;
73
- __idForPointAnnotation?: string;
74
-
75
- _idForPointAnnotation(): string {
76
- if (this.__idForPointAnnotation === undefined) {
77
- MarkerView.lastId = MarkerView.lastId + 1;
78
- this.__idForPointAnnotation = `MV-${MarkerView.lastId}`;
79
- }
80
- return this.__idForPointAnnotation;
81
- }
82
-
83
- _getCoordinate(coordinate: Position): string | undefined {
84
- if (!coordinate) {
85
- return undefined;
86
- }
87
- return toJSONString(makePoint(coordinate));
68
+ const MarkerView = ({
69
+ anchor = DEFAULT_ANCHOR,
70
+ allowOverlap = false,
71
+ allowOverlapWithPuck = false,
72
+ isSelected = false,
73
+ coordinate,
74
+ style,
75
+ children,
76
+ }: Props) => {
77
+ // Android new-arch (Fabric) fix: UIManager.measure reads from the Fabric shadow
78
+ // tree, which doesn't include Mapbox's native setTranslationX/Y positioning.
79
+ // Strategy: intercept setTranslationX/Y on the native side (see
80
+ // RNMBXMarkerViewContent.kt), relay the values as an onAnnotationPosition event,
81
+ // then apply them as a React `transform` on RNMBXMarkerView so the shadow tree
82
+ // reflects the actual on-screen position. This makes
83
+ // Pressability._responderRegion correct and onPress / touch feedback work.
84
+ //
85
+ // Key details:
86
+ // • position:'absolute' on RNMBXMarkerView → all markers have Yoga pos (0,0)
87
+ // in MapView, so the only shadow-tree offset is the transform itself.
88
+ // • Transform goes on RNMBXMarkerView (not RNMBXMarkerViewContent) so Fabric
89
+ // never fights Mapbox's native positioning.
90
+ // • PIXEL_RATIO: Android translationX/Y is in device pixels; React transform
91
+ // expects logical pixels (points).
92
+ const [annotationTranslate, setAnnotationTranslate] = useState<{
93
+ x: number;
94
+ y: number;
95
+ } | null>(null);
96
+
97
+ // Mirror of Kotlin-side dedup: skip setState when position hasn't changed so
98
+ // we don't trigger a re-render for no-op native position re-applications.
99
+ const lastTranslateRef = useRef<{ x: number; y: number } | null>(null);
100
+
101
+ const handleTouchEnd = useCallback((e: { stopPropagation: () => void }) => {
102
+ e.stopPropagation();
103
+ }, []);
104
+
105
+ const handleAnnotationPosition = useCallback(
106
+ (e: NativeSyntheticEvent<{ x: number; y: number }>) => {
107
+ const x = e.nativeEvent.x / PIXEL_RATIO;
108
+ const y = e.nativeEvent.y / PIXEL_RATIO;
109
+ const last = lastTranslateRef.current;
110
+ if (last !== null && last.x === x && last.y === y) return;
111
+ lastTranslateRef.current = { x, y };
112
+ setAnnotationTranslate({ x, y });
113
+ },
114
+ [],
115
+ );
116
+
117
+ if (anchor.x < 0 || anchor.y < 0 || anchor.x > 1 || anchor.y > 1) {
118
+ console.warn(
119
+ `[MarkerView] Anchor with value (${anchor.x}, ${anchor.y}) should not be outside the range [(0, 0), (1, 1)]`,
120
+ );
88
121
  }
89
122
 
90
- render() {
91
- if (
92
- this.props.anchor.x < 0 ||
93
- this.props.anchor.y < 0 ||
94
- this.props.anchor.x > 1 ||
95
- this.props.anchor.y > 1
96
- ) {
97
- console.warn(
98
- `[MarkerView] Anchor with value (${this.props.anchor.x}, ${this.props.anchor.y}) should not be outside the range [(0, 0), (1, 1)]`,
99
- );
100
- }
101
-
102
- if (Platform.OS === 'ios' && !Mapbox.MapboxV10) {
103
- return (
104
- <PointAnnotation id={this._idForPointAnnotation()} {...this.props} />
105
- );
106
- }
107
-
108
- const { anchor = { x: 0.5, y: 0.5 } } = this.props;
109
-
110
- return (
111
- <RNMBXMarkerView
112
- style={[
113
- {
114
- flex: 0,
115
- alignSelf: 'flex-start',
116
- },
117
- this.props.style,
118
- ]}
119
- coordinate={[
120
- Number(this.props.coordinate[0]),
121
- Number(this.props.coordinate[1]),
122
- ]}
123
- anchor={anchor}
124
- allowOverlap={this.props.allowOverlap}
125
- allowOverlapWithPuck={this.props.allowOverlapWithPuck}
126
- isSelected={this.props.isSelected}
127
- onTouchEnd={(e) => {
128
- e.stopPropagation();
129
- }}
123
+ const nativeCoordinate = useMemo(
124
+ () => [Number(coordinate[0]), Number(coordinate[1])] as [number, number],
125
+ // eslint-disable-next-line react-hooks/exhaustive-deps
126
+ [coordinate[0], coordinate[1]],
127
+ );
128
+
129
+ const nativeStyle = useMemo(
130
+ () => [
131
+ styles.absolutePosition,
132
+ style,
133
+ annotationTranslate != null
134
+ ? {
135
+ transform: [
136
+ { translateX: annotationTranslate.x },
137
+ { translateY: annotationTranslate.y },
138
+ ],
139
+ }
140
+ : undefined,
141
+ ],
142
+ [style, annotationTranslate],
143
+ );
144
+
145
+ return (
146
+ <RNMBXMarkerView
147
+ style={nativeStyle}
148
+ coordinate={nativeCoordinate}
149
+ anchor={anchor}
150
+ allowOverlap={allowOverlap}
151
+ allowOverlapWithPuck={allowOverlapWithPuck}
152
+ isSelected={isSelected}
153
+ onTouchEnd={handleTouchEnd}
154
+ >
155
+ <RNMBXMakerViewContentComponent
156
+ collapsable={false}
157
+ style={styles.contentContainer}
158
+ onAnnotationPosition={handleAnnotationPosition}
130
159
  >
131
- <RNMBXMakerViewContentComponent
132
- collapsable={false}
133
- style={{ flex: 0, alignSelf: 'flex-start' }}
134
- onStartShouldSetResponder={(_event) => {
135
- return true;
136
- }}
137
- onTouchEnd={(e) => {
138
- e.stopPropagation();
139
- }}
140
- >
141
- {this.props.children}
142
- </RNMBXMakerViewContentComponent>
143
- </RNMBXMarkerView>
144
- );
145
- }
146
- }
160
+ {children}
161
+ </RNMBXMakerViewContentComponent>
162
+ </RNMBXMarkerView>
163
+ );
164
+ };
147
165
 
148
166
  const RNMBXMarkerView = NativeMarkerViewComponent;
149
167
 
168
+ const styles = StyleSheet.create({
169
+ absolutePosition: { position: 'absolute' },
170
+ contentContainer: { flex: 0, alignSelf: 'flex-start' },
171
+ });
172
+
150
173
  export default MarkerView;
@@ -259,9 +259,10 @@ class UserLocation extends React.Component<Props, UserLocationState> {
259
259
  _renderNative() {
260
260
  const { androidRenderMode, showsUserHeadingIndicator } = this.props;
261
261
 
262
- const props = {
262
+ const props: React.ComponentProps<typeof LocationPuck> = {
263
263
  androidRenderMode,
264
- iosShowsUserHeadingIndicator: showsUserHeadingIndicator,
264
+ puckBearingEnabled: showsUserHeadingIndicator,
265
+ puckBearing: showsUserHeadingIndicator ? 'heading' : undefined,
265
266
  };
266
267
  return <LocationPuck {...props} />;
267
268
  }
@@ -182,14 +182,7 @@ class OfflineManager {
182
182
  * @return {void}
183
183
  */
184
184
  async invalidateAmbientCache(): Promise<void> {
185
- if (RNMBXModule.MapboxV10) {
186
- console.warn(
187
- 'RNMapbox: invalidateAmbientCache is not implemented on v10',
188
- );
189
- return;
190
- }
191
- await this._initialize();
192
- await MapboxOfflineManager.invalidateAmbientCache();
185
+ console.warn('RNMapbox: invalidateAmbientCache is not implemented on v10');
193
186
  }
194
187
 
195
188
  /**
@@ -204,12 +197,7 @@ class OfflineManager {
204
197
  * @return {void}
205
198
  */
206
199
  async clearAmbientCache(): Promise<void> {
207
- if (RNMBXModule.MapboxV10) {
208
- console.warn('RNMapbox: clearAmbientCache is not implemented on v10');
209
- return;
210
- }
211
- await this._initialize();
212
- await MapboxOfflineManager.clearAmbientCache();
200
+ console.warn('RNMapbox: clearAmbientCache is not implemented on v10');
213
201
  }
214
202
 
215
203
  /**
@@ -1,7 +1,19 @@
1
1
  import type { HostComponent, ViewProps } from 'react-native';
2
2
  import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
3
+ // @ts-ignore - CI environment type resolution issue for CodegenTypes
4
+ import { DirectEventHandler, Float } from 'react-native/Libraries/Types/CodegenTypes';
3
5
 
4
- export interface NativeProps extends ViewProps {}
6
+ type OnAnnotationPositionEvent = {
7
+ x: Float;
8
+ y: Float;
9
+ };
10
+
11
+ export interface NativeProps extends ViewProps {
12
+ // Fired by native when Mapbox repositions the annotation via setTranslationX/Y.
13
+ // JS uses this to keep the Fabric shadow tree transform in sync so that
14
+ // UIManager.measure returns the correct on-screen position for Pressable hit-testing.
15
+ onAnnotationPosition?: DirectEventHandler<OnAnnotationPositionEvent>;
16
+ }
5
17
 
6
18
  // @ts-ignore-error - Codegen requires single cast but TypeScript prefers double cast
7
19
  export default codegenNativeComponent<NativeProps>(
@@ -28,6 +28,7 @@ export interface NativeProps extends ViewProps {
28
28
  draggable: UnsafeMixed<boolean>;
29
29
  id: UnsafeMixed<string>;
30
30
  anchor: UnsafeMixed<any>;
31
+ selected: UnsafeMixed<boolean>;
31
32
 
32
33
  onMapboxPointAnnotationDeselected: DirectEventHandler<OnMapboxPointAnnotationDeselectedEventType>;
33
34
  onMapboxPointAnnotationDrag: DirectEventHandler<OnMapboxPointAnnotationDragEventType>;
@@ -729,6 +729,24 @@ export interface LineLayerStyleProps {
729
729
  * The line part between [trimStart, trimEnd] will be painted using `lineTrimColor,` which is transparent by default to produce a route vanishing effect. The line trimOff offset is based on the whole line range [0.0, 1.0].
730
730
  */
731
731
  lineTrimOffset?: number[];
732
+ /**
733
+ * The width of the line border. A value of zero means no border.
734
+ */
735
+ lineBorderWidth?: Value<number, ['zoom', 'feature', 'feature-state']>;
736
+
737
+ /**
738
+ * The transition affecting any changes to this layer’s lineBorderWidth property.
739
+ */
740
+ lineBorderWidthTransition?: Transition;
741
+ /**
742
+ * The color of the line border. If lineBorderWidth is greater than zero and the alpha value of this color is 0 (default), the color for the border will be selected automatically based on the line color.
743
+ */
744
+ lineBorderColor?: Value<string, ['zoom', 'feature', 'feature-state']>;
745
+
746
+ /**
747
+ * The transition affecting any changes to this layer’s lineBorderColor property.
748
+ */
749
+ lineBorderColorTransition?: Transition;
732
750
  /**
733
751
  * Vertical offset from ground, in meters. Not supported for globe projection at the moment.
734
752
  *
@@ -66,6 +66,10 @@ const styleMap = {
66
66
  linePattern: StyleTypes.Image,
67
67
  lineGradient: StyleTypes.Color,
68
68
  lineTrimOffset: StyleTypes.Constant,
69
+ lineBorderWidth: StyleTypes.Constant,
70
+ lineBorderWidthTransition: StyleTypes.Transition,
71
+ lineBorderColor: StyleTypes.Color,
72
+ lineBorderColorTransition: StyleTypes.Transition,
69
73
  lineZOffset: StyleTypes.Constant,
70
74
  lineElevationReference: StyleTypes.Enum,
71
75
  lineCrossSlope: StyleTypes.Constant,