@lugg/maps 1.0.0-beta.4 → 1.0.0-beta.6

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 (104) hide show
  1. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +4 -2
  2. package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +4 -3
  3. package/android/src/main/java/com/luggmaps/LuggMapView.kt +40 -0
  4. package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +31 -0
  5. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +23 -0
  6. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +13 -0
  7. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +166 -21
  8. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +5 -0
  9. package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +11 -0
  10. package/ios/LuggCalloutView.h +1 -1
  11. package/ios/LuggCalloutView.mm +21 -11
  12. package/ios/LuggMapView.mm +41 -2
  13. package/ios/LuggMarkerView.h +3 -0
  14. package/ios/LuggMarkerView.mm +23 -0
  15. package/ios/core/AppleMapProvider.mm +236 -16
  16. package/ios/core/GoogleMapProvider.mm +91 -18
  17. package/ios/core/MapProviderDelegate.h +8 -1
  18. package/lib/module/MapProvider.web.js +4 -1
  19. package/lib/module/MapProvider.web.js.map +1 -1
  20. package/lib/module/MapView.js +12 -1
  21. package/lib/module/MapView.js.map +1 -1
  22. package/lib/module/MapView.web.js +21 -18
  23. package/lib/module/MapView.web.js.map +1 -1
  24. package/lib/module/components/Circle.web.js +3 -3
  25. package/lib/module/components/Circle.web.js.map +1 -1
  26. package/lib/module/components/GeoJson.js +3 -3
  27. package/lib/module/components/GeoJson.js.map +1 -1
  28. package/lib/module/components/GroundOverlay.web.js +3 -3
  29. package/lib/module/components/GroundOverlay.web.js.map +1 -1
  30. package/lib/module/components/Marker.js +17 -3
  31. package/lib/module/components/Marker.js.map +1 -1
  32. package/lib/module/components/Marker.web.js +23 -10
  33. package/lib/module/components/Marker.web.js.map +1 -1
  34. package/lib/module/components/Polygon.web.js +3 -3
  35. package/lib/module/components/Polygon.web.js.map +1 -1
  36. package/lib/module/components/Polyline.web.js +6 -12
  37. package/lib/module/components/Polyline.web.js.map +1 -1
  38. package/lib/module/components/TileOverlay.web.js +3 -3
  39. package/lib/module/components/TileOverlay.web.js.map +1 -1
  40. package/lib/module/components/index.js.map +1 -1
  41. package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  42. package/lib/module/fabric/LuggMapViewNativeComponent.ts +9 -1
  43. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/typescript/src/MapProvider.web.d.ts +3 -2
  46. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
  47. package/lib/typescript/src/MapView.d.ts +1 -1
  48. package/lib/typescript/src/MapView.d.ts.map +1 -1
  49. package/lib/typescript/src/MapView.types.d.ts +36 -1
  50. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  51. package/lib/typescript/src/MapView.web.d.ts +1 -1
  52. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  53. package/lib/typescript/src/components/Circle.web.d.ts +1 -1
  54. package/lib/typescript/src/components/Circle.web.d.ts.map +1 -1
  55. package/lib/typescript/src/components/GeoJson.d.ts +2 -1
  56. package/lib/typescript/src/components/GeoJson.d.ts.map +1 -1
  57. package/lib/typescript/src/components/GroundOverlay.web.d.ts +1 -1
  58. package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -1
  59. package/lib/typescript/src/components/Marker.d.ts +6 -3
  60. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  61. package/lib/typescript/src/components/Marker.types.d.ts +14 -5
  62. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
  63. package/lib/typescript/src/components/Marker.web.d.ts +3 -2
  64. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  65. package/lib/typescript/src/components/Polygon.web.d.ts +1 -1
  66. package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -1
  67. package/lib/typescript/src/components/Polyline.web.d.ts +1 -1
  68. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
  69. package/lib/typescript/src/components/TileOverlay.web.d.ts +1 -1
  70. package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -1
  71. package/lib/typescript/src/components/index.d.ts +1 -1
  72. package/lib/typescript/src/components/index.d.ts.map +1 -1
  73. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +1 -1
  74. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +6 -1
  75. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
  76. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +8 -1
  77. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  78. package/lib/typescript/src/index.d.ts +3 -3
  79. package/lib/typescript/src/index.d.ts.map +1 -1
  80. package/lib/typescript/src/index.web.d.ts +1 -1
  81. package/lib/typescript/src/index.web.d.ts.map +1 -1
  82. package/lib/typescript/src/types.d.ts +0 -4
  83. package/lib/typescript/src/types.d.ts.map +1 -1
  84. package/package.json +1 -1
  85. package/src/MapProvider.web.tsx +5 -3
  86. package/src/MapView.tsx +12 -1
  87. package/src/MapView.types.ts +118 -1
  88. package/src/MapView.web.tsx +378 -345
  89. package/src/components/Circle.web.tsx +81 -79
  90. package/src/components/GeoJson.tsx +3 -3
  91. package/src/components/GroundOverlay.web.tsx +65 -69
  92. package/src/components/Marker.tsx +28 -5
  93. package/src/components/Marker.types.ts +15 -5
  94. package/src/components/Marker.web.tsx +196 -150
  95. package/src/components/Polygon.web.tsx +93 -89
  96. package/src/components/Polyline.web.tsx +235 -235
  97. package/src/components/TileOverlay.web.tsx +83 -81
  98. package/src/components/index.ts +1 -0
  99. package/src/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  100. package/src/fabric/LuggMapViewNativeComponent.ts +9 -1
  101. package/src/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  102. package/src/index.ts +6 -1
  103. package/src/index.web.ts +3 -0
  104. package/src/types.ts +0 -5
@@ -1,93 +1,95 @@
1
- import { useCallback, useEffect, useRef } from 'react';
1
+ import { memo, useCallback, useEffect, useRef } from 'react';
2
2
  import { useMapContext } from '../MapProvider.web';
3
3
  import type { CircleProps } from './Circle.types';
4
4
 
5
- export const Circle = ({
6
- center,
7
- radius,
8
- strokeColor = '#000000',
9
- strokeWidth = 1,
10
- fillColor = 'rgba(0, 0, 0, 0.3)',
11
- zIndex = 0,
12
- onPress,
13
- }: CircleProps) => {
14
- const { map } = useMapContext();
15
- const circleRef = useRef<google.maps.Circle | null>(null);
16
- const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
5
+ export const Circle = memo(
6
+ ({
7
+ center,
8
+ radius,
9
+ strokeColor = '#000000',
10
+ strokeWidth = 1,
11
+ fillColor = 'rgba(0, 0, 0, 0.3)',
12
+ zIndex = 0,
13
+ onPress,
14
+ }: CircleProps) => {
15
+ const { map } = useMapContext();
16
+ const circleRef = useRef<google.maps.Circle | null>(null);
17
+ const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
17
18
 
18
- const handleClick = useCallback(() => {
19
- onPress?.();
20
- }, [onPress]);
19
+ const handleClick = useCallback(() => {
20
+ onPress?.();
21
+ }, [onPress]);
21
22
 
22
- useEffect(() => {
23
- return () => {
24
- listenersRef.current.forEach((l) => l.remove());
25
- listenersRef.current = [];
26
- circleRef.current?.setMap(null);
27
- circleRef.current = null;
28
- };
29
- }, []);
23
+ useEffect(() => {
24
+ return () => {
25
+ listenersRef.current.forEach((l) => l.remove());
26
+ listenersRef.current = [];
27
+ circleRef.current?.setMap(null);
28
+ circleRef.current = null;
29
+ };
30
+ }, []);
30
31
 
31
- useEffect(() => {
32
- const circle = circleRef.current;
33
- if (!circle) return;
32
+ useEffect(() => {
33
+ const circle = circleRef.current;
34
+ if (!circle) return;
34
35
 
35
- listenersRef.current.forEach((l) => l.remove());
36
- listenersRef.current = [];
36
+ listenersRef.current.forEach((l) => l.remove());
37
+ listenersRef.current = [];
37
38
 
38
- if (onPress) {
39
- listenersRef.current.push(circle.addListener('click', handleClick));
40
- }
41
- circle.set('clickable', !!onPress);
42
- }, [onPress, handleClick]);
39
+ if (onPress) {
40
+ listenersRef.current.push(circle.addListener('click', handleClick));
41
+ }
42
+ circle.set('clickable', !!onPress);
43
+ }, [onPress, handleClick]);
43
44
 
44
- useEffect(() => {
45
- if (!map) {
46
- circleRef.current?.setMap(null);
47
- return;
48
- }
45
+ useEffect(() => {
46
+ if (!map) {
47
+ circleRef.current?.setMap(null);
48
+ return;
49
+ }
49
50
 
50
- const googleCenter = { lat: center.latitude, lng: center.longitude };
51
+ const googleCenter = { lat: center.latitude, lng: center.longitude };
51
52
 
52
- if (circleRef.current) {
53
- circleRef.current.setCenter(googleCenter);
54
- circleRef.current.setRadius(radius);
55
- circleRef.current.setOptions({
56
- strokeColor: strokeColor as string,
57
- strokeWeight: strokeWidth,
58
- fillColor: fillColor as string,
59
- zIndex,
60
- });
61
- } else {
62
- const circle = new google.maps.Circle({
63
- center: googleCenter,
64
- radius,
65
- strokeColor: strokeColor as string,
66
- strokeWeight: strokeWidth,
67
- strokeOpacity: 1,
68
- fillColor: fillColor as string,
69
- fillOpacity: 1,
70
- zIndex,
71
- clickable: !!onPress,
72
- map,
73
- });
74
- circleRef.current = circle;
53
+ if (circleRef.current) {
54
+ circleRef.current.setCenter(googleCenter);
55
+ circleRef.current.setRadius(radius);
56
+ circleRef.current.setOptions({
57
+ strokeColor: strokeColor as string,
58
+ strokeWeight: strokeWidth,
59
+ fillColor: fillColor as string,
60
+ zIndex,
61
+ });
62
+ } else {
63
+ const circle = new google.maps.Circle({
64
+ center: googleCenter,
65
+ radius,
66
+ strokeColor: strokeColor as string,
67
+ strokeWeight: strokeWidth,
68
+ strokeOpacity: 1,
69
+ fillColor: fillColor as string,
70
+ fillOpacity: 1,
71
+ zIndex,
72
+ clickable: !!onPress,
73
+ map,
74
+ });
75
+ circleRef.current = circle;
75
76
 
76
- if (onPress) {
77
- listenersRef.current.push(circle.addListener('click', handleClick));
77
+ if (onPress) {
78
+ listenersRef.current.push(circle.addListener('click', handleClick));
79
+ }
78
80
  }
79
- }
80
- }, [
81
- map,
82
- center,
83
- radius,
84
- strokeColor,
85
- strokeWidth,
86
- fillColor,
87
- zIndex,
88
- onPress,
89
- handleClick,
90
- ]);
81
+ }, [
82
+ map,
83
+ center,
84
+ radius,
85
+ strokeColor,
86
+ strokeWidth,
87
+ fillColor,
88
+ zIndex,
89
+ onPress,
90
+ handleClick,
91
+ ]);
91
92
 
92
- return null;
93
- };
93
+ return null;
94
+ }
95
+ );
@@ -1,4 +1,4 @@
1
- import React, { useMemo, type ReactElement } from 'react';
1
+ import React, { memo, useMemo, type ReactElement } from 'react';
2
2
  import type {
3
3
  Feature,
4
4
  FeatureCollection,
@@ -199,7 +199,7 @@ const renderGeometry = (
199
199
  return elements;
200
200
  };
201
201
 
202
- export const GeoJson = (props: GeoJsonProps) => {
202
+ export const GeoJson = memo((props: GeoJsonProps) => {
203
203
  const { geojson } = props;
204
204
 
205
205
  const elements = useMemo(() => {
@@ -218,4 +218,4 @@ export const GeoJson = (props: GeoJsonProps) => {
218
218
  }, [geojson, props]);
219
219
 
220
220
  return <>{elements}</>;
221
- };
221
+ });
@@ -1,85 +1,81 @@
1
- import { useCallback, useEffect, useRef } from 'react';
1
+ import { memo, useCallback, useEffect, useRef } from 'react';
2
2
  import { useMapContext } from '../MapProvider.web';
3
3
  import type { GroundOverlayProps } from './GroundOverlay.types';
4
4
 
5
- export const GroundOverlay = ({
6
- image,
7
- bounds,
8
- opacity = 1,
9
- zIndex = 0,
10
- onPress,
11
- }: GroundOverlayProps) => {
12
- const { map } = useMapContext();
13
- const overlayRef = useRef<google.maps.GroundOverlay | null>(null);
14
- const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
5
+ export const GroundOverlay = memo(
6
+ ({ image, bounds, opacity = 1, zIndex = 0, onPress }: GroundOverlayProps) => {
7
+ const { map } = useMapContext();
8
+ const overlayRef = useRef<google.maps.GroundOverlay | null>(null);
9
+ const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
15
10
 
16
- const handleClick = useCallback(() => {
17
- onPress?.();
18
- }, [onPress]);
11
+ const handleClick = useCallback(() => {
12
+ onPress?.();
13
+ }, [onPress]);
14
+
15
+ // Cleanup on unmount
16
+ useEffect(() => {
17
+ return () => {
18
+ listenersRef.current.forEach((l) => l.remove());
19
+ listenersRef.current = [];
20
+ overlayRef.current?.setMap(null);
21
+ overlayRef.current = null;
22
+ };
23
+ }, []);
24
+
25
+ // Sync listeners
26
+ useEffect(() => {
27
+ const overlay = overlayRef.current;
28
+ if (!overlay) return;
19
29
 
20
- // Cleanup on unmount
21
- useEffect(() => {
22
- return () => {
23
30
  listenersRef.current.forEach((l) => l.remove());
24
31
  listenersRef.current = [];
25
- overlayRef.current?.setMap(null);
26
- overlayRef.current = null;
27
- };
28
- }, []);
29
32
 
30
- // Sync listeners
31
- useEffect(() => {
32
- const overlay = overlayRef.current;
33
- if (!overlay) return;
33
+ if (onPress) {
34
+ listenersRef.current.push(overlay.addListener('click', handleClick));
35
+ }
36
+ overlay.set('clickable', !!onPress);
37
+ }, [onPress, handleClick]);
34
38
 
35
- listenersRef.current.forEach((l) => l.remove());
36
- listenersRef.current = [];
39
+ // Sync overlay with props
40
+ useEffect(() => {
41
+ if (!map) {
42
+ overlayRef.current?.setMap(null);
43
+ return;
44
+ }
37
45
 
38
- if (onPress) {
39
- listenersRef.current.push(overlay.addListener('click', handleClick));
40
- }
41
- overlay.set('clickable', !!onPress);
42
- }, [onPress, handleClick]);
43
-
44
- // Sync overlay with props
45
- useEffect(() => {
46
- if (!map) {
47
- overlayRef.current?.setMap(null);
48
- return;
49
- }
46
+ const source =
47
+ typeof image === 'number'
48
+ ? null
49
+ : Array.isArray(image)
50
+ ? image[0]
51
+ : image;
52
+ const imageUrl = source?.uri ?? '';
53
+ if (!imageUrl) return;
50
54
 
51
- const source =
52
- typeof image === 'number'
53
- ? null
54
- : Array.isArray(image)
55
- ? image[0]
56
- : image;
57
- const imageUrl = source?.uri ?? '';
58
- if (!imageUrl) return;
55
+ const latLngBounds = new google.maps.LatLngBounds(
56
+ { lat: bounds.southwest.latitude, lng: bounds.southwest.longitude },
57
+ { lat: bounds.northeast.latitude, lng: bounds.northeast.longitude }
58
+ );
59
59
 
60
- const latLngBounds = new google.maps.LatLngBounds(
61
- { lat: bounds.southwest.latitude, lng: bounds.southwest.longitude },
62
- { lat: bounds.northeast.latitude, lng: bounds.northeast.longitude }
63
- );
64
-
65
- // GroundOverlay bounds are immutable — recreate if bounds change
66
- overlayRef.current?.setMap(null);
67
- listenersRef.current.forEach((l) => l.remove());
68
- listenersRef.current = [];
60
+ // GroundOverlay bounds are immutable — recreate if bounds change
61
+ overlayRef.current?.setMap(null);
62
+ listenersRef.current.forEach((l) => l.remove());
63
+ listenersRef.current = [];
69
64
 
70
- const overlay = new google.maps.GroundOverlay(imageUrl, latLngBounds, {
71
- opacity,
72
- clickable: !!onPress,
73
- map,
74
- });
65
+ const overlay = new google.maps.GroundOverlay(imageUrl, latLngBounds, {
66
+ opacity,
67
+ clickable: !!onPress,
68
+ map,
69
+ });
75
70
 
76
- overlay.set('zIndex', zIndex);
77
- overlayRef.current = overlay;
71
+ overlay.set('zIndex', zIndex);
72
+ overlayRef.current = overlay;
78
73
 
79
- if (onPress) {
80
- listenersRef.current.push(overlay.addListener('click', handleClick));
81
- }
82
- }, [map, image, bounds, opacity, zIndex, onPress, handleClick]);
74
+ if (onPress) {
75
+ listenersRef.current.push(overlay.addListener('click', handleClick));
76
+ }
77
+ }, [map, image, bounds, opacity, zIndex, onPress, handleClick]);
83
78
 
84
- return null;
85
- };
79
+ return null;
80
+ }
81
+ );
@@ -1,12 +1,15 @@
1
1
  import React, { isValidElement } from 'react';
2
2
  import { StyleSheet } from 'react-native';
3
- import LuggMarkerViewNativeComponent from '../fabric/LuggMarkerViewNativeComponent';
3
+ import LuggMarkerViewNativeComponent, {
4
+ Commands,
5
+ } from '../fabric/LuggMarkerViewNativeComponent';
4
6
  import LuggCalloutViewNativeComponent from '../fabric/LuggCalloutViewNativeComponent';
5
- import type { MarkerProps } from './Marker.types';
7
+ import type { MarkerProps, MarkerRef } from './Marker.types';
6
8
  import type { Point } from '../types';
7
9
 
8
10
  export type {
9
11
  CalloutOptions,
12
+ MarkerRef,
10
13
  MarkerProps,
11
14
  MarkerPressEvent,
12
15
  MarkerDragEvent,
@@ -14,7 +17,24 @@ export type {
14
17
 
15
18
  const DEFAULT_ANCHOR: Point = { x: 0.5, y: 1 };
16
19
 
17
- export class Marker extends React.PureComponent<MarkerProps> {
20
+ export class Marker
21
+ extends React.PureComponent<MarkerProps>
22
+ implements MarkerRef
23
+ {
24
+ private nativeRef = React.createRef<any>();
25
+
26
+ showCallout() {
27
+ const ref = this.nativeRef.current;
28
+ if (!ref) return;
29
+ Commands.showCallout(ref);
30
+ }
31
+
32
+ hideCallout() {
33
+ const ref = this.nativeRef.current;
34
+ if (!ref) return;
35
+ Commands.hideCallout(ref);
36
+ }
37
+
18
38
  private getStyle(zIndex: number | undefined) {
19
39
  if (zIndex == null) return styles.marker;
20
40
  if (zIndex !== this._cachedZIndex) {
@@ -38,6 +58,7 @@ export class Marker extends React.PureComponent<MarkerProps> {
38
58
  rotate = 0,
39
59
  scale = 1,
40
60
  rasterize = true,
61
+ centerOnPress = true,
41
62
  draggable = false,
42
63
  onPress,
43
64
  onDragStart,
@@ -54,10 +75,11 @@ export class Marker extends React.PureComponent<MarkerProps> {
54
75
  : React.createElement(callout)
55
76
  : null;
56
77
  const calloutBubbled = calloutOptions?.bubbled ?? true;
57
- const calloutAnchor = calloutOptions?.anchor;
78
+ const calloutOffset = calloutOptions?.offset;
58
79
 
59
80
  return (
60
81
  <LuggMarkerViewNativeComponent
82
+ ref={this.nativeRef}
61
83
  style={this.getStyle(zIndex)}
62
84
  name={name}
63
85
  coordinate={coordinate}
@@ -67,6 +89,7 @@ export class Marker extends React.PureComponent<MarkerProps> {
67
89
  rotate={rotate}
68
90
  scale={scale}
69
91
  rasterize={rasterize}
92
+ centerOnPress={centerOnPress}
70
93
  draggable={draggable}
71
94
  onMarkerPress={onPress}
72
95
  onMarkerDragStart={onDragStart}
@@ -78,7 +101,7 @@ export class Marker extends React.PureComponent<MarkerProps> {
78
101
  <LuggCalloutViewNativeComponent
79
102
  style={calloutStyles.callout}
80
103
  bubbled={calloutBubbled}
81
- anchor={calloutAnchor}
104
+ offset={calloutOffset}
82
105
  >
83
106
  {calloutContent}
84
107
  </LuggCalloutViewNativeComponent>
@@ -14,13 +14,18 @@ export interface CalloutOptions {
14
14
  */
15
15
  bubbled?: boolean;
16
16
  /**
17
- * Anchor point for the callout relative to the marker position.
18
- * `{x: 0.5, y: 1}` places the bottom-center of the callout at the marker.
17
+ * Pixel offset for non-bubbled callouts from their default centered position above the marker.
18
+ * Positive `x` moves right, positive `y` moves down.
19
+ * Only applies when `bubbled` is `false`.
19
20
  *
20
- * @note Not supported on web.
21
- * @default {x: 0.5, y: 1}
21
+ * @default {x: 0, y: 0}
22
22
  */
23
- anchor?: Point;
23
+ offset?: Point;
24
+ }
25
+
26
+ export interface MarkerRef {
27
+ showCallout(): void;
28
+ hideCallout(): void;
24
29
  }
25
30
 
26
31
  export interface MarkerProps {
@@ -68,6 +73,11 @@ export interface MarkerProps {
68
73
  * @default true
69
74
  */
70
75
  rasterize?: boolean;
76
+ /**
77
+ * Whether the map centers on the marker when pressed.
78
+ * @default true
79
+ */
80
+ centerOnPress?: boolean;
71
81
  /**
72
82
  * Whether the marker can be dragged by the user.
73
83
  * @default false