@maplibre/maplibre-react-native 10.0.0-alpha.6 → 10.0.0-alpha.8

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 (113) 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 +7 -0
  14. package/CONTRIBUTING.md +10 -9
  15. package/android/build.gradle +1 -1
  16. package/android/rctmln/build.gradle +5 -5
  17. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/MarkerView.java +2 -2
  18. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/MarkerViewManager.java +6 -6
  19. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/RCTMLNMarkerView.java +5 -5
  20. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/RCTMLNPointAnnotation.java +9 -8
  21. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/CameraStop.java +14 -12
  22. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/CameraUpdateItem.java +10 -10
  23. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/CameraUpdateQueue.java +1 -1
  24. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/RCTMLNCamera.java +26 -26
  25. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/RCTMLNCameraManager.java +1 -1
  26. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/images/RCTMLNImages.java +12 -12
  27. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/location/LocationComponentManager.java +9 -9
  28. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/location/RCTMLNNativeUserLocation.java +7 -7
  29. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/location/RCTMLNNativeUserLocationManager.java +1 -1
  30. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/LayerSourceInfo.java +9 -9
  31. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNAndroidTextureMapView.java +2 -2
  32. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNAndroidTextureMapViewManager.java +2 -2
  33. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNMapView.java +43 -43
  34. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNMapViewManager.java +6 -6
  35. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyle.java +3 -3
  36. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyleFactory.java +14 -14
  37. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyleFunctionParser.java +2 -2
  38. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyleValue.java +2 -2
  39. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTLayer.java +8 -8
  40. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNBackgroundLayer.java +1 -1
  41. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNCircleLayer.java +2 -2
  42. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNFillExtrusionLayer.java +2 -2
  43. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNFillLayer.java +2 -2
  44. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNHeatmapLayer.java +2 -2
  45. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNLineLayer.java +2 -2
  46. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNRasterLayer.java +1 -1
  47. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNSymbolLayer.java +2 -2
  48. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/light/RCTMLNLight.java +6 -6
  49. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNImageSource.java +3 -3
  50. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNImageSourceManager.java +1 -1
  51. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNRasterSource.java +3 -3
  52. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNShapeSource.java +9 -9
  53. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNShapeSourceManager.java +1 -1
  54. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNTileSource.java +2 -2
  55. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNVectorSource.java +4 -4
  56. package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTSource.java +7 -7
  57. package/android/rctmln/src/main/java/com/maplibre/rctmln/events/FeatureClickEvent.java +2 -2
  58. package/android/rctmln/src/main/java/com/maplibre/rctmln/events/MapClickEvent.java +1 -1
  59. package/android/rctmln/src/main/java/com/maplibre/rctmln/events/PointAnnotationClickEvent.java +2 -2
  60. package/android/rctmln/src/main/java/com/maplibre/rctmln/events/PointAnnotationDragEvent.java +2 -2
  61. package/android/rctmln/src/main/java/com/maplibre/rctmln/location/LocationManager.java +6 -6
  62. package/android/rctmln/src/main/java/com/maplibre/rctmln/location/UserLocation.java +1 -1
  63. package/android/rctmln/src/main/java/com/maplibre/rctmln/location/UserTrackingMode.java +3 -3
  64. package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNLocationModule.java +2 -2
  65. package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNLogging.java +2 -2
  66. package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNModule.java +8 -8
  67. package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNOfflineModule.java +11 -11
  68. package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNSnapshotModule.java +7 -7
  69. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/ClusterPropertyEntry.java +1 -1
  70. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/DownloadMapImageTask.java +5 -5
  71. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/ExpressionParser.java +2 -2
  72. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/GeoJSONUtils.java +13 -13
  73. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/GeoViewport.java +3 -3
  74. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/SimpleEventCallback.java +2 -2
  75. package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/SphericalMercator.java +1 -1
  76. package/docs/Camera.md +3 -3
  77. package/docs/MapView.md +9 -33
  78. package/docs/UserLocation.md +10 -2
  79. package/docs/docs.json +16 -31
  80. package/javascript/Maplibre.ts +5 -1
  81. package/javascript/components/BackgroundLayer.tsx +27 -20
  82. package/javascript/components/Callout.tsx +40 -40
  83. package/javascript/components/Camera.tsx +421 -478
  84. package/javascript/components/CircleLayer.tsx +29 -22
  85. package/javascript/components/FillExtrusionLayer.tsx +23 -23
  86. package/javascript/components/FillLayer.tsx +22 -19
  87. package/javascript/components/HeatmapLayer.tsx +21 -19
  88. package/javascript/components/ImageSource.tsx +25 -32
  89. package/javascript/components/Images.tsx +36 -35
  90. package/javascript/components/Light.tsx +20 -47
  91. package/javascript/components/LineLayer.tsx +23 -20
  92. package/javascript/components/MapView.tsx +604 -554
  93. package/javascript/components/MarkerView.tsx +23 -38
  94. package/javascript/components/NativeUserLocation.tsx +3 -5
  95. package/javascript/components/PointAnnotation.tsx +111 -87
  96. package/javascript/components/RasterLayer.tsx +21 -18
  97. package/javascript/components/RasterSource.tsx +39 -42
  98. package/javascript/components/ShapeSource.tsx +287 -239
  99. package/javascript/components/Style.tsx +1 -1
  100. package/javascript/components/SymbolLayer.tsx +34 -28
  101. package/javascript/components/UserLocation.tsx +164 -151
  102. package/javascript/components/VectorSource.tsx +128 -117
  103. package/javascript/components/annotations/Annotation.tsx +105 -79
  104. package/javascript/{components/AbstractLayer.tsx → hooks/useAbstractLayer.ts} +54 -37
  105. package/javascript/hooks/useAbstractSource.ts +34 -0
  106. package/javascript/hooks/useNativeBridge.ts +125 -0
  107. package/javascript/hooks/useNativeRef.ts +13 -0
  108. package/javascript/hooks/useOnce.ts +12 -0
  109. package/javascript/utils/Logger.ts +3 -3
  110. package/package.json +2 -1
  111. package/scripts/templates/RCTMLNStyleFactory.java.ejs +14 -14
  112. package/javascript/components/AbstractSource.tsx +0 -27
  113. package/javascript/components/NativeBridgeComponent.tsx +0 -117
@@ -4,7 +4,12 @@ import AnimatedMapPoint from '../../utils/animated/AnimatedPoint';
4
4
  import OnPressEvent from '../../types/OnPressEvent';
5
5
  import {SymbolLayerStyleProps} from '../../utils/MaplibreStyles';
6
6
 
7
- import React, {ReactElement} from 'react';
7
+ import React, {
8
+ ReactElement,
9
+ useCallback,
10
+ useEffect,
11
+ useImperativeHandle,
12
+ } from 'react';
8
13
  import {Animated as RNAnimated, Easing} from 'react-native';
9
14
 
10
15
  interface AnnotationProps {
@@ -19,116 +24,137 @@ interface AnnotationProps {
19
24
  icon?: string | number | object;
20
25
  }
21
26
 
22
- type AnnotationState = {
23
- shape: AnimatedMapPoint | GeoJSON.Point | null;
24
- };
27
+ type Shape = AnimatedMapPoint | GeoJSON.Point;
25
28
 
26
- class Annotation extends React.Component<AnnotationProps, AnnotationState> {
27
- static defaultProps = {
28
- animated: false,
29
- animationDuration: 1000,
30
- animationEasingFunction: Easing.linear,
31
- };
29
+ function getShapeFromProps(props: Partial<AnnotationProps> = {}): Shape {
30
+ const lng = props.coordinates?.[0] || 0;
31
+ const lat = props.coordinates?.[1] || 0;
32
+ const point: GeoJSON.Point = {type: 'Point', coordinates: [lng, lat]};
32
33
 
33
- constructor(props: AnnotationProps) {
34
- super(props);
34
+ if (props.animated) {
35
+ return new AnimatedMapPoint(point);
36
+ }
37
+
38
+ return point;
39
+ }
35
40
 
36
- const shape = this._getShapeFromProps(props);
41
+ function isShapeAnimated(shape: Shape): shape is AnimatedMapPoint {
42
+ return shape instanceof AnimatedMapPoint;
43
+ }
37
44
 
38
- this.state = {
39
- shape: props.animated ? new AnimatedMapPoint(shape) : shape,
45
+ interface AnnotationRef {
46
+ onPress(event: OnPressEvent): void;
47
+ symbolStyle: SymbolLayerStyleProps | undefined;
48
+ }
49
+
50
+ const Annotation = React.forwardRef<AnnotationRef, AnnotationProps>(
51
+ (
52
+ {
53
+ animated = false,
54
+ animationDuration = 1000,
55
+ animationEasingFunction = Easing.linear,
56
+ ...otherProps
57
+ }: AnnotationProps,
58
+ ref,
59
+ ) => {
60
+ const props = {
61
+ ...otherProps,
62
+ animated,
63
+ animationDuration,
64
+ animationEasingFunction,
40
65
  };
41
66
 
42
- this.onPress = this.onPress.bind(this);
43
- }
67
+ useImperativeHandle(
68
+ ref,
69
+ (): AnnotationRef => ({
70
+ onPress,
71
+ symbolStyle,
72
+ }),
73
+ );
44
74
 
45
- componentDidUpdate(prevProps: AnnotationProps): void {
46
- if (!Array.isArray(this.props.coordinates)) {
47
- this.setState({shape: null});
48
- return;
49
- }
75
+ const [shape, setShape] = React.useState<Shape | null>(
76
+ getShapeFromProps(props),
77
+ );
50
78
 
51
- const hasCoordChanged =
52
- prevProps.coordinates?.[0] !== this.props.coordinates?.[0] ||
53
- prevProps.coordinates?.[1] !== this.props.coordinates?.[1];
79
+ // this will run useEffect only when actual coordinates values change
80
+ const coordinateDeps = props.coordinates?.join(',');
54
81
 
55
- if (!hasCoordChanged) {
56
- return;
57
- }
82
+ useEffect(() => {
83
+ if (!Array.isArray(props.coordinates)) {
84
+ setShape(null);
85
+ return;
86
+ }
58
87
 
59
- if (this.props.animated && this.state.shape) {
60
- // flush current animations
61
- (this.state.shape as AnimatedMapPoint).stopAnimation();
62
-
63
- (this.state.shape as AnimatedMapPoint)
64
- .timing({
65
- coordinates: this.props.coordinates,
66
- easing: this.props.animationEasingFunction,
67
- duration: this.props.animationDuration,
68
- })
69
- .start();
70
- } else if (!this.state.shape || !this.props.animated) {
71
- const shape = this._getShapeFromProps();
72
-
73
- this.setState({
74
- shape: this.props.animated ? new AnimatedMapPoint(shape) : shape,
75
- });
76
- }
77
- }
88
+ if (shape && isShapeAnimated(shape)) {
89
+ shape.stopAnimation();
78
90
 
79
- onPress(event: OnPressEvent): void {
80
- if (this.props.onPress) {
81
- this.props.onPress(event);
82
- }
83
- }
91
+ shape
92
+ .timing({
93
+ coordinates: props.coordinates,
94
+ easing: animationEasingFunction,
95
+ duration: animationDuration,
96
+ })
97
+ .start();
84
98
 
85
- _getShapeFromProps(props: Partial<AnnotationProps> = {}): GeoJSON.Point {
86
- const lng = props.coordinates?.[0] || 0;
87
- const lat = props.coordinates?.[1] || 0;
88
- return {type: 'Point', coordinates: [lng, lat]};
89
- }
99
+ return;
100
+ }
101
+
102
+ if (!shape || !isShapeAnimated(shape)) {
103
+ const newShape = getShapeFromProps(props);
104
+ setShape(newShape);
105
+ }
106
+ }, [coordinateDeps]);
107
+
108
+ const onPressProp = props.onPress;
90
109
 
91
- get symbolStyle(): SymbolLayerStyleProps | undefined {
92
- if (!this.props.icon) {
93
- return undefined;
110
+ const _onPress = useCallback(
111
+ (event: OnPressEvent) => {
112
+ if (onPressProp) {
113
+ onPressProp(event);
114
+ }
115
+ },
116
+ [onPressProp],
117
+ );
118
+
119
+ // This function is needed to correctly generate Annotation.md doc
120
+ function onPress(event: OnPressEvent): void {
121
+ _onPress(event);
94
122
  }
95
- return Object.assign({}, this.props.style, {
96
- iconImage: this.props.icon,
97
- });
98
- }
99
123
 
100
- render(): ReactElement | null {
101
- if (!this.props.coordinates) {
124
+ if (!props.coordinates) {
102
125
  return null;
103
126
  }
104
127
 
105
128
  const children = [];
129
+ const symbolStyle: SymbolLayerStyleProps | undefined = props.icon
130
+ ? {...props.style, iconImage: props.icon}
131
+ : undefined;
106
132
 
107
- if (this.symbolStyle) {
133
+ if (symbolStyle) {
108
134
  children.push(
109
- <SymbolLayer id={`${this.props.id}-symbol`} style={this.symbolStyle} />,
135
+ <SymbolLayer id={`${props.id}-symbol`} style={symbolStyle} />,
110
136
  );
111
137
  }
112
138
 
113
- if (this.props.children) {
114
- if (Array.isArray(this.props.children)) {
115
- children.push(...this.props.children);
139
+ if (props.children) {
140
+ if (Array.isArray(props.children)) {
141
+ children.push(...props.children);
116
142
  } else {
117
- children.push(this.props.children);
143
+ children.push(props.children);
118
144
  }
119
145
  }
120
146
 
121
147
  return (
122
148
  <Animated.ShapeSource
123
- id={this.props.id}
124
- onPress={this.onPress}
125
- shape={
126
- this.state.shape as RNAnimated.WithAnimatedObject<GeoJSON.Point>
127
- }>
149
+ id={props.id}
150
+ onPress={_onPress}
151
+ shape={shape as RNAnimated.WithAnimatedObject<GeoJSON.Point>}>
128
152
  {children}
129
153
  </Animated.ShapeSource>
130
154
  );
131
- }
132
- }
155
+ },
156
+ );
157
+
158
+ Annotation.displayName = 'Annotation';
133
159
 
134
160
  export default Annotation;
@@ -1,10 +1,14 @@
1
- /* eslint react/prop-types:0 */
2
1
  import {StyleValue, transformStyle} from '../utils/StyleValue';
3
2
  import {getFilter} from '../utils/filterUtils';
4
- import {AllLayerStyleProps, FilterExpression} from '../utils/MaplibreStyles';
3
+ import {
4
+ AllLayerStyleProps,
5
+ ExpressionField,
6
+ ExpressionName,
7
+ FilterExpression,
8
+ } from '../utils/MaplibreStyles';
5
9
  import BaseProps from '../types/BaseProps';
6
10
 
7
- import React from 'react';
11
+ import React, {useMemo, useRef} from 'react';
8
12
  import {processColor, NativeMethods} from 'react-native';
9
13
 
10
14
  export interface BaseLayerProps {
@@ -56,52 +60,65 @@ export interface NativeBaseProps {
56
60
  reactStyle?: {[key: string]: StyleValue};
57
61
  }
58
62
 
59
- class AbstractLayer<
63
+ export default function useAbstractLayer<
60
64
  Props extends BaseProps,
61
65
  NativeProps extends NativeBaseProps,
62
- > extends React.PureComponent<Props & BaseLayerProps> {
63
- get baseProps(): Props {
66
+ >(
67
+ props: Props & BaseLayerProps,
68
+ ): {
69
+ baseProps: Props & BaseLayerProps;
70
+ setNativeLayer: (
71
+ instance: (React.Component<NativeProps> & Readonly<NativeMethods>) | null,
72
+ ) => void;
73
+ getStyleTypeFormatter: (styleType: string) => typeof processColor | undefined;
74
+ setNativeProps: (nativeProps: {[key: string]: unknown}) => void;
75
+ } {
76
+ const nativeLayer = useRef<
77
+ (React.Component<NativeProps> & Readonly<NativeMethods>) | null
78
+ >(null);
79
+
80
+ const baseProps = useMemo(() => {
64
81
  return {
65
- ...this.props,
66
- id: this.props.id,
67
- sourceID: this.props.sourceID,
68
- reactStyle: this.getStyle(),
69
- minZoomLevel: this.props.minZoomLevel,
70
- maxZoomLevel: this.props.maxZoomLevel,
71
- aboveLayerID: this.props.aboveLayerID,
72
- belowLayerID: this.props.belowLayerID,
73
- layerIndex: this.props.layerIndex,
74
- filter: getFilter(this.props.filter),
82
+ ...props,
83
+ id: props.id,
84
+ sourceID: props.sourceID,
85
+ reactStyle: transformStyle(props.style),
86
+ minZoomLevel: props.minZoomLevel,
87
+ maxZoomLevel: props.maxZoomLevel,
88
+ aboveLayerID: props.aboveLayerID,
89
+ belowLayerID: props.belowLayerID,
90
+ layerIndex: props.layerIndex,
91
+ filter: getFilter(props.filter) as [ExpressionName, ...ExpressionField[]],
75
92
  style: undefined,
76
93
  };
77
- }
78
-
79
- nativeLayer: (React.Component<NativeProps> & Readonly<NativeMethods>) | null =
80
- null;
94
+ }, [props]);
81
95
 
82
- setNativeLayer = (
96
+ const setNativeLayer = (
83
97
  instance: (React.Component<NativeProps> & Readonly<NativeMethods>) | null,
84
98
  ): void => {
85
- this.nativeLayer = instance;
99
+ nativeLayer.current = instance;
86
100
  };
87
101
 
88
- getStyleTypeFormatter(styleType: string): typeof processColor | undefined {
102
+ const getStyleTypeFormatter = (
103
+ styleType: string,
104
+ ): typeof processColor | undefined => {
89
105
  return styleType === 'color' ? processColor : undefined;
90
- }
91
-
92
- getStyle(): {[key: string]: StyleValue} | undefined {
93
- return transformStyle(this.props.style);
94
- }
106
+ };
95
107
 
96
- setNativeProps(props: {[key: string]: unknown}): void {
97
- if (this.nativeLayer) {
98
- let propsToPass = props;
99
- if (props.style) {
100
- propsToPass = {...props, reactStyle: this.getStyle()};
108
+ const setNativeProps = (nativeProps: {[key: string]: unknown}): void => {
109
+ if (nativeLayer.current) {
110
+ let propsToPass = nativeProps;
111
+ if (nativeProps.style) {
112
+ propsToPass = {...nativeProps, reactStyle: transformStyle(props.style)};
101
113
  }
102
- this.nativeLayer.setNativeProps(propsToPass);
114
+ nativeLayer.current.setNativeProps(propsToPass);
103
115
  }
104
- }
105
- }
116
+ };
106
117
 
107
- export default AbstractLayer;
118
+ return {
119
+ baseProps,
120
+ setNativeLayer,
121
+ getStyleTypeFormatter,
122
+ setNativeProps,
123
+ };
124
+ }
@@ -0,0 +1,34 @@
1
+ import React, {useRef} from 'react';
2
+ import {NativeMethods} from 'react-native';
3
+
4
+ export default function useAbstractSource<NativePropsType extends object>(): {
5
+ _nativeRef:
6
+ | (React.Component<NativePropsType> & Readonly<NativeMethods>)
7
+ | undefined;
8
+ setNativeRef: (
9
+ instance: React.Component<NativePropsType> & Readonly<NativeMethods>,
10
+ ) => void;
11
+ setNativeProps: (nativeProps: NativePropsType) => void;
12
+ } {
13
+ const _nativeRef = useRef<
14
+ (React.Component<NativePropsType> & Readonly<NativeMethods>) | undefined
15
+ >(undefined);
16
+
17
+ const setNativeRef = (
18
+ instance: React.Component<NativePropsType> & Readonly<NativeMethods>,
19
+ ): void => {
20
+ _nativeRef.current = instance;
21
+ };
22
+
23
+ const setNativeProps = (newProps: NativePropsType): void => {
24
+ if (_nativeRef.current) {
25
+ _nativeRef.current.setNativeProps(newProps);
26
+ }
27
+ };
28
+
29
+ return {
30
+ _nativeRef: _nativeRef.current,
31
+ setNativeRef,
32
+ setNativeProps,
33
+ };
34
+ }
@@ -0,0 +1,125 @@
1
+ import {runNativeCommand, isAndroid, NativeArg} from '../utils';
2
+
3
+ import React, {Component, SyntheticEvent, useRef} from 'react';
4
+
5
+ export type RNMLEvent<PayloadType = {[key: string]: string}> = {
6
+ payload: PayloadType;
7
+ type: string;
8
+ };
9
+
10
+ let callbackIncrement = 0;
11
+
12
+ type UseNativeBridge = {
13
+ _nativeModuleName: string;
14
+ _onAndroidCallback: (e: SyntheticEvent<Element, RNMLEvent>) => void;
15
+ _callbackMap: React.MutableRefObject<Map<string, any>>;
16
+ _preRefMapMethodQueue: React.MutableRefObject<any[]>;
17
+ _addAddAndroidCallback: <ReturnType>(
18
+ id: string,
19
+ resolve: (value: ReturnType) => void,
20
+ reject: (error: Error) => void,
21
+ ) => void;
22
+ _removeAndroidCallback: (id: string) => void;
23
+ _runPendingNativeCommands: <RefType extends Component>(
24
+ nativeRef: RefType | null | undefined,
25
+ ) => Promise<void>;
26
+ _runNativeCommand: <RefType extends Component, ReturnType = NativeArg>(
27
+ methodName: string,
28
+ nativeRef: RefType | undefined | null,
29
+ args?: NativeArg[],
30
+ ) => Promise<ReturnType>;
31
+ };
32
+
33
+ const useNativeBridge: (moduleName: string) => UseNativeBridge = (
34
+ _nativeModuleName: string,
35
+ ) => {
36
+ const _callbackMap = useRef<Map<string, any>>(new Map());
37
+ const _preRefMapMethodQueue = useRef<any[]>([]);
38
+
39
+ const _addAddAndroidCallback = <ReturnType>(
40
+ id: string,
41
+ resolve: (value: ReturnType) => void,
42
+ reject: (error: Error) => void,
43
+ ): void => {
44
+ _callbackMap.current.set(id, {resolve, reject});
45
+ };
46
+
47
+ const _removeAndroidCallback = (id: string): void => {
48
+ _callbackMap.current.delete(id);
49
+ };
50
+
51
+ const _onAndroidCallback = (e: SyntheticEvent<Element, RNMLEvent>): void => {
52
+ const callbackID = e.nativeEvent.type;
53
+ const callback = _callbackMap.current.get(callbackID);
54
+
55
+ if (!callback) {
56
+ return;
57
+ }
58
+
59
+ _callbackMap.current.delete(callbackID);
60
+ const {payload} = e.nativeEvent;
61
+ if (payload.error) {
62
+ callback.reject.call(null, new Error(payload.error));
63
+ } else {
64
+ callback.resolve.call(null, payload);
65
+ }
66
+ };
67
+
68
+ const _runPendingNativeCommands = async <RefType extends Component>(
69
+ nativeRef: RefType | null | undefined,
70
+ ): Promise<void> => {
71
+ if (nativeRef) {
72
+ while (_preRefMapMethodQueue.current.length > 0) {
73
+ const item = _preRefMapMethodQueue.current.pop();
74
+
75
+ if (item && item.method && item.resolver) {
76
+ const res = await _runNativeCommand(
77
+ item.method.name,
78
+ nativeRef,
79
+ item.method.args,
80
+ );
81
+ item.resolver(res);
82
+ }
83
+ }
84
+ }
85
+ };
86
+
87
+ const _runNativeCommand = <RefType extends Component, ReturnType = NativeArg>(
88
+ methodName: string,
89
+ nativeRef: RefType | undefined | null,
90
+ args: NativeArg[] = [],
91
+ ): Promise<ReturnType> => {
92
+ if (!nativeRef) {
93
+ return new Promise(resolve => {
94
+ _preRefMapMethodQueue.current.push({
95
+ method: {name: methodName, args},
96
+ resolver: resolve,
97
+ });
98
+ });
99
+ }
100
+
101
+ if (isAndroid()) {
102
+ return new Promise((resolve, reject) => {
103
+ callbackIncrement += 1;
104
+ const callbackID = `${methodName}_${callbackIncrement}`;
105
+ _addAddAndroidCallback(callbackID, resolve, reject);
106
+ args.unshift(callbackID);
107
+ runNativeCommand(_nativeModuleName, methodName, nativeRef, args);
108
+ });
109
+ }
110
+ return runNativeCommand(_nativeModuleName, methodName, nativeRef, args);
111
+ };
112
+
113
+ return {
114
+ _nativeModuleName,
115
+ _onAndroidCallback,
116
+ _callbackMap,
117
+ _preRefMapMethodQueue,
118
+ _addAddAndroidCallback,
119
+ _removeAndroidCallback,
120
+ _runPendingNativeCommands,
121
+ _runNativeCommand,
122
+ };
123
+ };
124
+
125
+ export default useNativeBridge;
@@ -0,0 +1,13 @@
1
+ import React, {Component, useRef} from 'react';
2
+ import {NativeMethods} from 'react-native';
3
+
4
+ type NativeRef<NativeProps> = Component<NativeProps> & Readonly<NativeMethods>;
5
+
6
+ /**
7
+ * Separate module which allows to be mocked in tests.
8
+ */
9
+ export function useNativeRef<NativeProps = object>(): React.RefObject<
10
+ NativeRef<NativeProps>
11
+ > {
12
+ return useRef<NativeRef<NativeProps>>(null);
13
+ }
@@ -0,0 +1,12 @@
1
+ import {useRef} from 'react';
2
+
3
+ const useOnce: (callback: () => void) => void = (callback: () => void) => {
4
+ const once = useRef(false);
5
+
6
+ if (!once.current) {
7
+ once.current = true;
8
+ callback();
9
+ }
10
+ };
11
+
12
+ export default useOnce;
@@ -120,11 +120,11 @@ class Logger {
120
120
  const {message} = log;
121
121
  const level = this.effectiveLevel(log);
122
122
  if (level === 'error') {
123
- console.error('Mapbox error', message, log);
123
+ console.error('MapLibre error', message, log);
124
124
  } else if (level === 'warning') {
125
- console.warn('Mapbox warning', message, log);
125
+ console.warn('MapLibre warning', message, log);
126
126
  } else {
127
- console.log(`Mapbox [${level}]`, message, log);
127
+ console.log(`MapLibre [${level}]`, message, log);
128
128
  }
129
129
  }
130
130
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maplibre/maplibre-react-native",
3
3
  "description": "A MapLibre GL Native plugin for creating maps in React Native",
4
- "version": "10.0.0-alpha.6",
4
+ "version": "10.0.0-alpha.8",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -28,6 +28,7 @@
28
28
  "unittest:single": "jest --testNamePattern",
29
29
  "lint": "eslint .",
30
30
  "lint:fix": "eslint . --fix",
31
+ "lint:single": "eslint",
31
32
  "prepack": "pinst --disable && yarn build:plugin",
32
33
  "test:plugin": "jest plugin",
33
34
  "build:plugin": "tsc --build plugin",
@@ -6,20 +6,20 @@
6
6
 
7
7
  package com.maplibre.rctmln.components.styles;
8
8
 
9
- import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
10
- import com.mapbox.mapboxsdk.style.layers.CircleLayer;
11
- import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
12
- import com.mapbox.mapboxsdk.style.layers.FillLayer;
13
- import com.mapbox.mapboxsdk.style.layers.LineLayer;
14
- import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
15
- import com.mapbox.mapboxsdk.style.layers.PropertyValue;
16
- import com.mapbox.mapboxsdk.style.layers.RasterLayer;
17
- import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
18
- import com.mapbox.mapboxsdk.style.layers.HeatmapLayer;
19
- import com.mapbox.mapboxsdk.style.layers.HillshadeLayer;
20
- import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
21
- import com.mapbox.mapboxsdk.style.light.Light;
22
- import com.mapbox.mapboxsdk.style.light.Position;
9
+ import org.maplibre.android.style.layers.BackgroundLayer;
10
+ import org.maplibre.android.style.layers.CircleLayer;
11
+ import org.maplibre.android.style.layers.FillExtrusionLayer;
12
+ import org.maplibre.android.style.layers.FillLayer;
13
+ import org.maplibre.android.style.layers.LineLayer;
14
+ import org.maplibre.android.style.layers.PropertyFactory;
15
+ import org.maplibre.android.style.layers.PropertyValue;
16
+ import org.maplibre.android.style.layers.RasterLayer;
17
+ import org.maplibre.android.style.layers.SymbolLayer;
18
+ import org.maplibre.android.style.layers.HeatmapLayer;
19
+ import org.maplibre.android.style.layers.HillshadeLayer;
20
+ import org.maplibre.android.style.layers.TransitionOptions;
21
+ import org.maplibre.android.style.light.Light;
22
+ import org.maplibre.android.style.light.Position;
23
23
  import com.maplibre.rctmln.utils.DownloadMapImageTask;
24
24
 
25
25
  import java.util.List;
@@ -1,27 +0,0 @@
1
- import BaseProps from '../types/BaseProps';
2
-
3
- import React from 'react';
4
- import {NativeMethods} from 'react-native';
5
-
6
- class AbstractSource<
7
- PropsType extends BaseProps,
8
- NativePropsType extends object,
9
- > extends React.PureComponent<PropsType> {
10
- _nativeRef?: React.Component<NativePropsType> & Readonly<NativeMethods>;
11
-
12
- setNativeProps(props: NativePropsType): void {
13
- if (this._nativeRef) {
14
- this._nativeRef.setNativeProps(props);
15
- }
16
- }
17
-
18
- setNativeRef: (
19
- instance: React.Component<NativePropsType> & Readonly<NativeMethods>,
20
- ) => void = (
21
- instance: React.Component<NativePropsType> & Readonly<NativeMethods>,
22
- ) => {
23
- this._nativeRef = instance;
24
- };
25
- }
26
-
27
- export default AbstractSource;