@lugg/maps 1.0.0-beta.2 → 1.0.0-beta.20

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 (206) hide show
  1. package/README.md +3 -0
  2. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +9 -2
  3. package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +4 -3
  4. package/android/src/main/java/com/luggmaps/LuggCircleView.kt +85 -0
  5. package/android/src/main/java/com/luggmaps/LuggCircleViewManager.kt +79 -0
  6. package/android/src/main/java/com/luggmaps/LuggGroundOverlayView.kt +81 -0
  7. package/android/src/main/java/com/luggmaps/LuggGroundOverlayViewManager.kt +82 -0
  8. package/android/src/main/java/com/luggmaps/LuggMapView.kt +90 -0
  9. package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +45 -0
  10. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +27 -2
  11. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +30 -2
  12. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +13 -0
  13. package/android/src/main/java/com/luggmaps/LuggPackage.kt +4 -1
  14. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +3 -23
  15. package/android/src/main/java/com/luggmaps/LuggTileOverlayView.kt +92 -0
  16. package/android/src/main/java/com/luggmaps/LuggTileOverlayViewManager.kt +80 -0
  17. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +676 -36
  18. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +15 -0
  19. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +65 -11
  20. package/android/src/main/java/com/luggmaps/events/CirclePressEvent.kt +12 -0
  21. package/android/src/main/java/com/luggmaps/events/GroundOverlayPressEvent.kt +12 -0
  22. package/android/src/main/java/com/luggmaps/events/TileOverlayPressEvent.kt +12 -0
  23. package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +11 -0
  24. package/ios/LuggCalloutView.h +1 -1
  25. package/ios/LuggCalloutView.mm +21 -11
  26. package/ios/LuggCircleView.h +31 -0
  27. package/ios/LuggCircleView.mm +133 -0
  28. package/ios/LuggGroundOverlayView.h +30 -0
  29. package/ios/LuggGroundOverlayView.mm +125 -0
  30. package/ios/LuggMapView.mm +254 -4
  31. package/ios/LuggMapWrapperView.h +5 -0
  32. package/ios/LuggMapWrapperView.mm +18 -0
  33. package/ios/LuggMarkerView.h +3 -0
  34. package/ios/LuggMarkerView.mm +25 -0
  35. package/ios/LuggTileOverlayView.h +31 -0
  36. package/ios/LuggTileOverlayView.mm +130 -0
  37. package/ios/core/AppleMapProvider.h +8 -0
  38. package/ios/core/AppleMapProvider.mm +663 -29
  39. package/ios/core/AppleStaticMapProvider.h +14 -0
  40. package/ios/core/AppleStaticMapProvider.mm +159 -0
  41. package/ios/core/GMSPolylineAnimator.m +46 -18
  42. package/ios/core/GoogleMapProvider.h +10 -0
  43. package/ios/core/GoogleMapProvider.mm +430 -51
  44. package/ios/core/GoogleStaticMapProvider.h +21 -0
  45. package/ios/core/GoogleStaticMapProvider.mm +213 -0
  46. package/ios/core/MKPolylineAnimator.m +67 -43
  47. package/ios/core/MapProviderDelegate.h +27 -1
  48. package/ios/core/StaticMapProviderBase.h +75 -0
  49. package/ios/core/StaticMapProviderBase.mm +845 -0
  50. package/ios/events/CameraIdleEvent.h +4 -2
  51. package/ios/events/CameraMoveEvent.h +4 -2
  52. package/ios/events/CirclePressEvent.h +22 -0
  53. package/ios/events/GroundOverlayPressEvent.h +22 -0
  54. package/ios/events/LongPressEvent.h +4 -2
  55. package/ios/events/MarkerDragEvent.h +12 -6
  56. package/ios/events/MarkerPressEvent.h +4 -2
  57. package/ios/events/PolygonPressEvent.h +4 -2
  58. package/ios/events/PressEvent.h +4 -2
  59. package/ios/events/ReadyEvent.h +4 -2
  60. package/ios/events/TileOverlayPressEvent.h +22 -0
  61. package/ios/extensions/MKMapView+Zoom.h +20 -0
  62. package/ios/extensions/MKMapView+Zoom.m +28 -18
  63. package/ios/extensions/UIView+Snapshot.h +16 -0
  64. package/ios/extensions/UIView+Snapshot.m +27 -0
  65. package/lib/module/MapProvider.web.js +4 -1
  66. package/lib/module/MapProvider.web.js.map +1 -1
  67. package/lib/module/MapView.js +19 -1
  68. package/lib/module/MapView.js.map +1 -1
  69. package/lib/module/MapView.web.js +30 -22
  70. package/lib/module/MapView.web.js.map +1 -1
  71. package/lib/module/components/Circle.js +46 -0
  72. package/lib/module/components/Circle.js.map +1 -0
  73. package/lib/module/components/Circle.types.js +4 -0
  74. package/lib/module/components/Circle.types.js.map +1 -0
  75. package/lib/module/components/Circle.web.js +79 -0
  76. package/lib/module/components/Circle.web.js.map +1 -0
  77. package/lib/module/components/GeoJson.js +3 -3
  78. package/lib/module/components/GeoJson.js.map +1 -1
  79. package/lib/module/components/GroundOverlay.js +45 -0
  80. package/lib/module/components/GroundOverlay.js.map +1 -0
  81. package/lib/module/components/GroundOverlay.types.js +4 -0
  82. package/lib/module/components/GroundOverlay.types.js.map +1 -0
  83. package/lib/module/components/GroundOverlay.web.js +77 -0
  84. package/lib/module/components/GroundOverlay.web.js.map +1 -0
  85. package/lib/module/components/Marker.js +22 -4
  86. package/lib/module/components/Marker.js.map +1 -1
  87. package/lib/module/components/Marker.web.js +23 -10
  88. package/lib/module/components/Marker.web.js.map +1 -1
  89. package/lib/module/components/Polygon.web.js +3 -3
  90. package/lib/module/components/Polygon.web.js.map +1 -1
  91. package/lib/module/components/Polyline.web.js +6 -12
  92. package/lib/module/components/Polyline.web.js.map +1 -1
  93. package/lib/module/components/TileOverlay.js +44 -0
  94. package/lib/module/components/TileOverlay.js.map +1 -0
  95. package/lib/module/components/TileOverlay.types.js +4 -0
  96. package/lib/module/components/TileOverlay.types.js.map +1 -0
  97. package/lib/module/components/TileOverlay.web.js +69 -0
  98. package/lib/module/components/TileOverlay.web.js.map +1 -0
  99. package/lib/module/components/index.js +3 -0
  100. package/lib/module/components/index.js.map +1 -1
  101. package/lib/module/components/index.web.js +3 -0
  102. package/lib/module/components/index.web.js.map +1 -1
  103. package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  104. package/lib/module/fabric/LuggCircleViewNativeComponent.ts +25 -0
  105. package/lib/module/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  106. package/lib/module/fabric/LuggMapViewNativeComponent.ts +16 -5
  107. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  108. package/lib/module/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  109. package/lib/module/index.js +3 -0
  110. package/lib/module/index.js.map +1 -1
  111. package/lib/module/index.web.js +3 -0
  112. package/lib/module/index.web.js.map +1 -1
  113. package/lib/typescript/src/MapProvider.web.d.ts +3 -2
  114. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
  115. package/lib/typescript/src/MapView.d.ts +1 -1
  116. package/lib/typescript/src/MapView.d.ts.map +1 -1
  117. package/lib/typescript/src/MapView.types.d.ts +60 -1
  118. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  119. package/lib/typescript/src/MapView.web.d.ts +1 -1
  120. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  121. package/lib/typescript/src/components/Circle.d.ts +10 -0
  122. package/lib/typescript/src/components/Circle.d.ts.map +1 -0
  123. package/lib/typescript/src/components/Circle.types.d.ts +33 -0
  124. package/lib/typescript/src/components/Circle.types.d.ts.map +1 -0
  125. package/lib/typescript/src/components/Circle.web.d.ts +3 -0
  126. package/lib/typescript/src/components/Circle.web.d.ts.map +1 -0
  127. package/lib/typescript/src/components/GeoJson.d.ts +2 -1
  128. package/lib/typescript/src/components/GeoJson.d.ts.map +1 -1
  129. package/lib/typescript/src/components/GroundOverlay.d.ts +10 -0
  130. package/lib/typescript/src/components/GroundOverlay.d.ts.map +1 -0
  131. package/lib/typescript/src/components/GroundOverlay.types.d.ts +35 -0
  132. package/lib/typescript/src/components/GroundOverlay.types.d.ts.map +1 -0
  133. package/lib/typescript/src/components/GroundOverlay.web.d.ts +3 -0
  134. package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -0
  135. package/lib/typescript/src/components/Marker.d.ts +6 -3
  136. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  137. package/lib/typescript/src/components/Marker.types.d.ts +18 -6
  138. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
  139. package/lib/typescript/src/components/Marker.web.d.ts +3 -2
  140. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  141. package/lib/typescript/src/components/Polygon.web.d.ts +1 -1
  142. package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -1
  143. package/lib/typescript/src/components/Polyline.web.d.ts +1 -1
  144. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
  145. package/lib/typescript/src/components/TileOverlay.d.ts +10 -0
  146. package/lib/typescript/src/components/TileOverlay.d.ts.map +1 -0
  147. package/lib/typescript/src/components/TileOverlay.types.d.ts +36 -0
  148. package/lib/typescript/src/components/TileOverlay.types.d.ts.map +1 -0
  149. package/lib/typescript/src/components/TileOverlay.web.d.ts +3 -0
  150. package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -0
  151. package/lib/typescript/src/components/index.d.ts +7 -1
  152. package/lib/typescript/src/components/index.d.ts.map +1 -1
  153. package/lib/typescript/src/components/index.web.d.ts +6 -0
  154. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  155. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +1 -1
  156. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts +18 -0
  157. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts.map +1 -0
  158. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts +21 -0
  159. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts.map +1 -0
  160. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +13 -5
  161. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
  162. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +8 -1
  163. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  164. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts +21 -0
  165. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts.map +1 -0
  166. package/lib/typescript/src/index.d.ts +9 -3
  167. package/lib/typescript/src/index.d.ts.map +1 -1
  168. package/lib/typescript/src/index.web.d.ts +7 -1
  169. package/lib/typescript/src/index.web.d.ts.map +1 -1
  170. package/lib/typescript/src/types.d.ts +0 -4
  171. package/lib/typescript/src/types.d.ts.map +1 -1
  172. package/package.json +17 -11
  173. package/src/MapProvider.web.tsx +5 -3
  174. package/src/MapView.tsx +19 -1
  175. package/src/MapView.types.ts +142 -1
  176. package/src/MapView.web.tsx +379 -340
  177. package/src/components/Circle.tsx +52 -0
  178. package/src/components/Circle.types.ts +33 -0
  179. package/src/components/Circle.web.tsx +95 -0
  180. package/src/components/GeoJson.tsx +3 -3
  181. package/src/components/GroundOverlay.tsx +47 -0
  182. package/src/components/GroundOverlay.types.ts +36 -0
  183. package/src/components/GroundOverlay.web.tsx +81 -0
  184. package/src/components/Marker.tsx +32 -6
  185. package/src/components/Marker.types.ts +19 -6
  186. package/src/components/Marker.web.tsx +196 -150
  187. package/src/components/Polygon.web.tsx +93 -89
  188. package/src/components/Polyline.web.tsx +235 -235
  189. package/src/components/TileOverlay.tsx +44 -0
  190. package/src/components/TileOverlay.types.ts +37 -0
  191. package/src/components/TileOverlay.web.tsx +97 -0
  192. package/src/components/index.ts +10 -0
  193. package/src/components/index.web.ts +9 -0
  194. package/src/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  195. package/src/fabric/LuggCircleViewNativeComponent.ts +25 -0
  196. package/src/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  197. package/src/fabric/LuggMapViewNativeComponent.ts +16 -5
  198. package/src/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  199. package/src/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  200. package/src/index.ts +12 -1
  201. package/src/index.web.ts +15 -0
  202. package/src/types.ts +0 -5
  203. package/plugin/build/withMapsAndroid.d.ts +0 -5
  204. package/plugin/build/withMapsAndroid.js +0 -15
  205. package/plugin/build/withMapsIOS.d.ts +0 -5
  206. package/plugin/build/withMapsIOS.js +0 -27
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  forwardRef,
3
+ memo,
3
4
  useCallback,
4
5
  useEffect,
5
6
  useId,
6
7
  useImperativeHandle,
8
+ useMemo,
7
9
  useRef,
8
10
  useState,
9
11
  type CSSProperties,
@@ -96,378 +98,415 @@ const UserLocationMarker = ({ enabled }: { enabled?: boolean }) => {
96
98
  );
97
99
  };
98
100
 
99
- export const MapView = forwardRef<MapViewRef, MapViewProps>(function MapView(
100
- props,
101
- ref
102
- ) {
103
- const {
104
- mapId = 'DEMO_MAP_ID',
105
- initialCoordinate,
106
- initialZoom = 10,
107
- minZoom,
108
- maxZoom,
109
- zoomEnabled = true,
110
- scrollEnabled = true,
111
- pitchEnabled = true,
112
- edgeInsets,
113
- userLocationEnabled,
114
- theme = 'system',
115
- onPress,
116
- onLongPress,
117
- onCameraMove,
118
- onCameraIdle,
119
- onReady,
120
- children,
121
- style,
122
- } = props;
123
-
124
- const id = useId();
125
- const map = useMap(id);
126
- const containerRef = useRef<View>(null);
127
- const readyFired = useRef(false);
128
- const [isDragging, setIsDragging] = useState(false);
129
- const wasGesture = useRef(false);
130
- const prevEdgeInsets = useRef(edgeInsets);
131
-
132
- const offsetCenter = useCallback(
133
- (coord: Coordinate, zoom: number, insets?: EdgeInsets, reverse = false) => {
134
- const p = insets ?? prevEdgeInsets.current;
135
- if (!p) {
136
- return { lat: coord.latitude, lng: coord.longitude };
137
- }
138
-
139
- const dir = reverse ? -1 : 1;
140
- const scale = 256 * Math.pow(2, zoom);
141
- const offsetX = (dir * ((p.right ?? 0) - (p.left ?? 0))) / 2;
142
- const offsetY = (dir * ((p.bottom ?? 0) - (p.top ?? 0))) / 2;
143
-
144
- const latRad = (coord.latitude * Math.PI) / 180;
145
- const x = ((coord.longitude + 180) / 360) * scale + offsetX;
146
- const y =
147
- ((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) /
148
- 2) *
149
- scale +
150
- offsetY;
151
-
152
- const lng = (x / scale) * 360 - 180;
153
- const lat =
154
- (Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / scale))) * 180) / Math.PI;
155
-
156
- return { lat, lng };
157
- },
158
- []
159
- );
160
-
161
- const applyEdgeInsets = useCallback(
162
- (newEdgeInsets: EdgeInsets, duration?: number) => {
163
- if (!map) return;
164
-
165
- const prev = prevEdgeInsets.current;
166
- const center = map.getCenter();
167
- const zoom = map.getZoom() ?? initialZoom;
168
-
169
- if (center) {
170
- const logicalCenter = offsetCenter(
171
- { latitude: center.lat(), longitude: center.lng() },
172
- zoom,
173
- prev,
174
- true
175
- );
176
- const newCenter = offsetCenter(
177
- { latitude: logicalCenter.lat, longitude: logicalCenter.lng },
178
- zoom,
179
- newEdgeInsets,
180
- false
181
- );
182
-
183
- if (duration === 0) {
184
- map.moveCamera({ center: newCenter, zoom });
185
- } else {
186
- map.panTo(newCenter);
101
+ export const MapView = memo(
102
+ forwardRef<MapViewRef, MapViewProps>(function MapView(props, ref) {
103
+ const {
104
+ mapType = 'standard',
105
+ mapId = 'DEMO_MAP_ID',
106
+ initialCoordinate,
107
+ initialZoom = 10,
108
+ minZoom,
109
+ maxZoom,
110
+ zoomEnabled = true,
111
+ scrollEnabled = true,
112
+ pitchEnabled = true,
113
+ compassEnabled = true,
114
+ staticMode = false,
115
+ edgeInsets,
116
+ userLocationEnabled,
117
+ theme = 'system',
118
+ onPress,
119
+ onLongPress,
120
+ onCameraMove,
121
+ onCameraIdle,
122
+ onReady,
123
+ children,
124
+ style,
125
+ } = props;
126
+
127
+ const id = useId();
128
+ const map = useMap(id);
129
+ const containerRef = useRef<View>(null);
130
+ const readyFired = useRef(false);
131
+ const isDraggingRef = useRef(false);
132
+ const wasGesture = useRef(false);
133
+ const prevEdgeInsets = useRef(edgeInsets);
134
+
135
+ const offsetCenter = useCallback(
136
+ (
137
+ coord: Coordinate,
138
+ zoom: number,
139
+ insets?: EdgeInsets,
140
+ reverse = false
141
+ ) => {
142
+ const p = insets ?? prevEdgeInsets.current;
143
+ if (!p) {
144
+ return { lat: coord.latitude, lng: coord.longitude };
187
145
  }
188
- }
189
146
 
190
- prevEdgeInsets.current = newEdgeInsets;
191
- },
192
- [map, initialZoom, offsetCenter]
193
- );
194
-
195
- const panToCoordinate = useCallback(
196
- (coordinate: Coordinate) => {
197
- if (!map) return;
198
- const zoom = map.getZoom() || initialZoom;
199
- const center = offsetCenter(coordinate, zoom, undefined, false);
200
- map.panTo(center);
201
- },
202
- [map, initialZoom, offsetCenter]
203
- );
147
+ const dir = reverse ? -1 : 1;
148
+ const scale = 256 * Math.pow(2, zoom);
149
+ const offsetX = (dir * ((p.right ?? 0) - (p.left ?? 0))) / 2;
150
+ const offsetY = (dir * ((p.bottom ?? 0) - (p.top ?? 0))) / 2;
151
+
152
+ const latRad = (coord.latitude * Math.PI) / 180;
153
+ const x = ((coord.longitude + 180) / 360) * scale + offsetX;
154
+ const y =
155
+ ((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) /
156
+ 2) *
157
+ scale +
158
+ offsetY;
159
+
160
+ const lng = (x / scale) * 360 - 180;
161
+ const lat =
162
+ (Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / scale))) * 180) /
163
+ Math.PI;
164
+
165
+ return { lat, lng };
166
+ },
167
+ []
168
+ );
204
169
 
205
- useImperativeHandle(
206
- ref,
207
- () => ({
208
- moveCamera(coordinate: Coordinate, options?: MoveCameraOptions) {
170
+ const applyEdgeInsets = useCallback(
171
+ (newEdgeInsets: EdgeInsets, duration?: number) => {
209
172
  if (!map) return;
210
173
 
211
- const { zoom = 0, duration = -1 } = options ?? {};
212
- const targetZoom = zoom || map.getZoom() || initialZoom;
213
- const center = offsetCenter(coordinate, targetZoom, undefined, false);
214
-
215
- if (duration === 0) {
216
- map.moveCamera({ center, zoom: targetZoom });
217
- } else {
218
- const currentZoom = map.getZoom();
219
- const zoomChanged = zoom !== 0 && zoom !== currentZoom;
220
-
221
- if (zoomChanged) {
222
- map.setZoom(zoom);
174
+ const prev = prevEdgeInsets.current;
175
+ const center = map.getCenter();
176
+ const zoom = map.getZoom() ?? initialZoom;
177
+
178
+ if (center) {
179
+ const logicalCenter = offsetCenter(
180
+ { latitude: center.lat(), longitude: center.lng() },
181
+ zoom,
182
+ prev,
183
+ true
184
+ );
185
+ const newCenter = offsetCenter(
186
+ { latitude: logicalCenter.lat, longitude: logicalCenter.lng },
187
+ zoom,
188
+ newEdgeInsets,
189
+ false
190
+ );
191
+
192
+ if (duration === 0) {
193
+ map.moveCamera({ center: newCenter, zoom });
194
+ } else {
195
+ map.panTo(newCenter);
223
196
  }
224
- map.panTo(center);
225
197
  }
198
+
199
+ prevEdgeInsets.current = newEdgeInsets;
226
200
  },
201
+ [map, initialZoom, offsetCenter]
202
+ );
227
203
 
228
- fitCoordinates(
229
- coordinates: Coordinate[],
230
- options?: FitCoordinatesOptions
231
- ) {
232
- const first = coordinates[0];
233
- if (!map || !first) return;
204
+ const panToCoordinate = useCallback(
205
+ (coordinate: Coordinate) => {
206
+ if (!map) return;
207
+ const zoom = map.getZoom() || initialZoom;
208
+ const center = offsetCenter(coordinate, zoom, undefined, false);
209
+ map.panTo(center);
210
+ },
211
+ [map, initialZoom, offsetCenter]
212
+ );
234
213
 
235
- const { padding: fitPadding, duration = -1 } = options ?? {};
214
+ useImperativeHandle(
215
+ ref,
216
+ () => ({
217
+ moveCamera(coordinate: Coordinate, options?: MoveCameraOptions) {
218
+ if (!map) return;
219
+
220
+ const { zoom = 0, duration = -1 } = options ?? {};
221
+ const targetZoom = zoom || map.getZoom() || initialZoom;
222
+ const center = offsetCenter(coordinate, targetZoom, undefined, false);
223
+
224
+ if (duration === 0) {
225
+ map.moveCamera({ center, zoom: targetZoom });
226
+ } else {
227
+ const currentZoom = map.getZoom();
228
+ const zoomChanged = zoom !== 0 && zoom !== currentZoom;
229
+
230
+ if (zoomChanged) {
231
+ map.setZoom(zoom);
232
+ }
233
+ map.panTo(center);
234
+ }
235
+ },
236
236
 
237
- if (coordinates.length === 1) {
238
- this.moveCamera(first, { zoom: initialZoom, duration });
239
- return;
240
- }
237
+ fitCoordinates(
238
+ coordinates: Coordinate[],
239
+ options?: FitCoordinatesOptions
240
+ ) {
241
+ const first = coordinates[0];
242
+ if (!map || !first) return;
241
243
 
242
- const bounds = new google.maps.LatLngBounds();
243
- coordinates.forEach((coord) => {
244
- bounds.extend({ lat: coord.latitude, lng: coord.longitude });
245
- });
244
+ const { padding: fitPadding, duration = -1 } = options ?? {};
246
245
 
247
- const ei = prevEdgeInsets.current;
248
- map.fitBounds(bounds, {
249
- top: (ei?.top ?? 0) + (fitPadding?.top ?? 0),
250
- left: (ei?.left ?? 0) + (fitPadding?.left ?? 0),
251
- bottom: (ei?.bottom ?? 0) + (fitPadding?.bottom ?? 0),
252
- right: (ei?.right ?? 0) + (fitPadding?.right ?? 0),
253
- });
254
- },
246
+ if (coordinates.length === 1) {
247
+ this.moveCamera(first, { zoom: initialZoom, duration });
248
+ return;
249
+ }
255
250
 
256
- setEdgeInsets(newEdgeInsets: EdgeInsets, options?: SetEdgeInsetsOptions) {
257
- applyEdgeInsets(newEdgeInsets, options?.duration);
258
- },
259
- }),
260
- [map, initialZoom, offsetCenter, applyEdgeInsets]
261
- );
251
+ const bounds = new google.maps.LatLngBounds();
252
+ coordinates.forEach((coord) => {
253
+ bounds.extend({ lat: coord.latitude, lng: coord.longitude });
254
+ });
255
+
256
+ const ei = prevEdgeInsets.current;
257
+ map.fitBounds(bounds, {
258
+ top: (ei?.top ?? 0) + (fitPadding?.top ?? 0),
259
+ left: (ei?.left ?? 0) + (fitPadding?.left ?? 0),
260
+ bottom: (ei?.bottom ?? 0) + (fitPadding?.bottom ?? 0),
261
+ right: (ei?.right ?? 0) + (fitPadding?.right ?? 0),
262
+ });
263
+ },
264
+
265
+ setEdgeInsets(
266
+ newEdgeInsets: EdgeInsets,
267
+ options?: SetEdgeInsetsOptions
268
+ ) {
269
+ applyEdgeInsets(newEdgeInsets, options?.duration);
270
+ },
271
+ }),
272
+ [map, initialZoom, offsetCenter, applyEdgeInsets]
273
+ );
262
274
 
263
- useEffect(() => {
264
- if (map && !readyFired.current) {
265
- readyFired.current = true;
266
- onReady?.();
267
- }
268
- }, [map, onReady]);
275
+ useEffect(() => {
276
+ if (map && !readyFired.current) {
277
+ readyFired.current = true;
278
+ onReady?.();
279
+ }
280
+ }, [map, onReady]);
269
281
 
270
- useEffect(() => {
271
- if (!map || !edgeInsets) return;
282
+ useEffect(() => {
283
+ if (!map || !edgeInsets) return;
272
284
 
273
- const prev = prevEdgeInsets.current;
274
- const changed =
275
- prev?.top !== edgeInsets.top ||
276
- prev?.left !== edgeInsets.left ||
277
- prev?.bottom !== edgeInsets.bottom ||
278
- prev?.right !== edgeInsets.right;
285
+ const prev = prevEdgeInsets.current;
286
+ const changed =
287
+ prev?.top !== edgeInsets.top ||
288
+ prev?.left !== edgeInsets.left ||
289
+ prev?.bottom !== edgeInsets.bottom ||
290
+ prev?.right !== edgeInsets.right;
291
+
292
+ if (changed) {
293
+ applyEdgeInsets(edgeInsets);
294
+ }
295
+ }, [map, edgeInsets, applyEdgeInsets]);
279
296
 
280
- if (changed) {
281
- applyEdgeInsets(edgeInsets);
282
- }
283
- }, [map, edgeInsets, applyEdgeInsets]);
284
-
285
- const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
286
- const longPressFired = useRef(false);
287
-
288
- const calloutListeners = useRef(new Set<() => void>()).current;
289
- const onCalloutClose = useCallback(
290
- (listener: () => void) => {
291
- calloutListeners.add(listener);
292
- return () => calloutListeners.delete(listener);
293
- },
294
- [calloutListeners]
295
- );
296
- const closeCallouts = useCallback(
297
- (except?: () => void) => {
298
- calloutListeners.forEach((l) => {
299
- if (l !== except) l();
300
- });
301
- },
302
- [calloutListeners]
303
- );
297
+ const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
298
+ const longPressFired = useRef(false);
304
299
 
305
- const getPoint = useCallback((domEvent?: Event) => {
306
- const el = containerRef.current as unknown as HTMLElement | null;
307
- if (!domEvent || !el) return { x: 0, y: 0 };
308
- const rect = el.getBoundingClientRect();
309
- const e = domEvent as MouseEvent | Touch;
310
- return { x: e.clientX - rect.left, y: e.clientY - rect.top };
311
- }, []);
312
-
313
- const handleClick = useCallback(
314
- (event: MapMouseEvent) => {
315
- if (longPressFired.current) {
316
- longPressFired.current = false;
317
- return;
318
- }
319
- closeCallouts();
320
- const latLng = event.detail.latLng;
321
- if (!onPress || !latLng) return;
322
- onPress(
323
- createSyntheticEvent({
324
- coordinate: { latitude: latLng.lat, longitude: latLng.lng },
325
- point: getPoint(event.domEvent),
326
- })
327
- );
328
- },
329
- [onPress, getPoint, closeCallouts]
330
- );
300
+ const calloutListeners = useRef(new Set<() => void>()).current;
301
+ const onCalloutClose = useCallback(
302
+ (listener: () => void) => {
303
+ calloutListeners.add(listener);
304
+ return () => calloutListeners.delete(listener);
305
+ },
306
+ [calloutListeners]
307
+ );
308
+ const closeCallouts = useCallback(
309
+ (except?: () => void) => {
310
+ calloutListeners.forEach((l) => {
311
+ if (l !== except) l();
312
+ });
313
+ },
314
+ [calloutListeners]
315
+ );
331
316
 
332
- const handleMouseDown = useCallback(
333
- (event: google.maps.MapMouseEvent) => {
334
- if (!onLongPress) return;
335
- const point = getPoint(event.domEvent);
336
- longPressFired.current = false;
337
- longPressTimer.current = setTimeout(() => {
338
- longPressFired.current = true;
339
- const latLng = event.latLng;
340
- if (!latLng) return;
341
- onLongPress(
317
+ const getPoint = useCallback((domEvent?: Event) => {
318
+ const el = containerRef.current as unknown as HTMLElement | null;
319
+ if (!domEvent || !el) return { x: 0, y: 0 };
320
+ const rect = el.getBoundingClientRect();
321
+ const e = domEvent as MouseEvent | Touch;
322
+ return { x: e.clientX - rect.left, y: e.clientY - rect.top };
323
+ }, []);
324
+
325
+ const handleClick = useCallback(
326
+ (event: MapMouseEvent) => {
327
+ if (longPressFired.current) {
328
+ longPressFired.current = false;
329
+ return;
330
+ }
331
+ closeCallouts();
332
+ const latLng = event.detail.latLng;
333
+ if (!onPress || !latLng) return;
334
+ onPress(
342
335
  createSyntheticEvent({
343
- coordinate: { latitude: latLng.lat(), longitude: latLng.lng() },
344
- point,
336
+ coordinate: { latitude: latLng.lat, longitude: latLng.lng },
337
+ point: getPoint(event.domEvent),
345
338
  })
346
339
  );
347
- }, 500);
348
- },
349
- [onLongPress, getPoint]
350
- );
340
+ },
341
+ [onPress, getPoint, closeCallouts]
342
+ );
351
343
 
352
- const handleMouseUp = useCallback(() => {
353
- if (longPressTimer.current) {
354
- clearTimeout(longPressTimer.current);
355
- longPressTimer.current = null;
356
- }
357
- }, []);
344
+ const handleMouseDown = useCallback(
345
+ (event: google.maps.MapMouseEvent) => {
346
+ if (!onLongPress) return;
347
+ const point = getPoint(event.domEvent);
348
+ longPressFired.current = false;
349
+ longPressTimer.current = setTimeout(() => {
350
+ longPressFired.current = true;
351
+ const latLng = event.latLng;
352
+ if (!latLng) return;
353
+ onLongPress(
354
+ createSyntheticEvent({
355
+ coordinate: { latitude: latLng.lat(), longitude: latLng.lng() },
356
+ point,
357
+ })
358
+ );
359
+ }, 500);
360
+ },
361
+ [onLongPress, getPoint]
362
+ );
358
363
 
359
- useEffect(() => {
360
- if (!map || !onLongPress) return;
361
- const listeners = [
362
- map.addListener('mousedown', handleMouseDown),
363
- map.addListener('mouseup', handleMouseUp),
364
- ];
365
- return () => {
366
- listeners.forEach((l) => google.maps.event.removeListener(l));
364
+ const handleMouseUp = useCallback(() => {
365
+ if (longPressTimer.current) {
366
+ clearTimeout(longPressTimer.current);
367
+ longPressTimer.current = null;
368
+ }
369
+ }, []);
370
+
371
+ useEffect(() => {
372
+ if (!map || !onLongPress || staticMode) return;
373
+ const listeners = [
374
+ map.addListener('mousedown', handleMouseDown),
375
+ map.addListener('mouseup', handleMouseUp),
376
+ ];
377
+ return () => {
378
+ listeners.forEach((l) => google.maps.event.removeListener(l));
379
+ handleMouseUp();
380
+ };
381
+ }, [map, onLongPress, staticMode, handleMouseDown, handleMouseUp]);
382
+
383
+ const handleDragStart = useCallback(() => {
367
384
  handleMouseUp();
368
- };
369
- }, [map, onLongPress, handleMouseDown, handleMouseUp]);
370
-
371
- const handleDragStart = () => {
372
- handleMouseUp();
373
- setIsDragging(true);
374
- wasGesture.current = true;
375
- };
376
-
377
- const handleDragEnd = () => {
378
- setIsDragging(false);
379
- };
380
-
381
- const handleCameraChanged = (event: MapCameraChangedEvent) => {
382
- const logicalCenter = offsetCenter(
383
- { latitude: event.detail.center.lat, longitude: event.detail.center.lng },
384
- event.detail.zoom,
385
- undefined,
386
- true
387
- );
388
- const payload: CameraEventPayload = {
389
- coordinate: {
390
- latitude: logicalCenter.lat,
391
- longitude: logicalCenter.lng,
385
+ isDraggingRef.current = true;
386
+ wasGesture.current = true;
387
+ }, [handleMouseUp]);
388
+
389
+ const handleDragEnd = useCallback(() => {
390
+ isDraggingRef.current = false;
391
+ }, []);
392
+
393
+ const handleCameraChanged = useCallback(
394
+ (event: MapCameraChangedEvent) => {
395
+ const logicalCenter = offsetCenter(
396
+ {
397
+ latitude: event.detail.center.lat,
398
+ longitude: event.detail.center.lng,
399
+ },
400
+ event.detail.zoom,
401
+ undefined,
402
+ true
403
+ );
404
+ const payload: CameraEventPayload = {
405
+ coordinate: {
406
+ latitude: logicalCenter.lat,
407
+ longitude: logicalCenter.lng,
408
+ },
409
+ zoom: event.detail.zoom,
410
+ gesture: isDraggingRef.current,
411
+ };
412
+ onCameraMove?.(createSyntheticEvent(payload));
392
413
  },
393
- zoom: event.detail.zoom,
394
- gesture: isDragging,
395
- };
396
- onCameraMove?.(createSyntheticEvent(payload));
397
- };
398
-
399
- const handleIdle = (event: MapEvent) => {
400
- const center = event.map.getCenter();
401
- const zoom = event.map.getZoom() ?? 0;
402
- const logicalCenter = offsetCenter(
403
- { latitude: center?.lat() ?? 0, longitude: center?.lng() ?? 0 },
404
- zoom,
405
- undefined,
406
- true
414
+ [offsetCenter, onCameraMove]
407
415
  );
408
- const payload: CameraEventPayload = {
409
- coordinate: {
410
- latitude: logicalCenter.lat,
411
- longitude: logicalCenter.lng,
416
+
417
+ const handleIdle = useCallback(
418
+ (event: MapEvent) => {
419
+ const center = event.map.getCenter();
420
+ const zoom = event.map.getZoom() ?? 0;
421
+ const logicalCenter = offsetCenter(
422
+ { latitude: center?.lat() ?? 0, longitude: center?.lng() ?? 0 },
423
+ zoom,
424
+ undefined,
425
+ true
426
+ );
427
+ const payload: CameraEventPayload = {
428
+ coordinate: {
429
+ latitude: logicalCenter.lat,
430
+ longitude: logicalCenter.lng,
431
+ },
432
+ zoom,
433
+ gesture: wasGesture.current,
434
+ };
435
+ onCameraIdle?.(createSyntheticEvent(payload));
436
+ wasGesture.current = false;
412
437
  },
413
- zoom,
414
- gesture: wasGesture.current,
415
- };
416
- onCameraIdle?.(createSyntheticEvent(payload));
417
- wasGesture.current = false;
418
- };
438
+ [offsetCenter, onCameraIdle]
439
+ );
440
+
441
+ const mapTypeId =
442
+ mapType === 'satellite'
443
+ ? 'satellite'
444
+ : mapType === 'terrain'
445
+ ? 'terrain'
446
+ : mapType === 'hybrid'
447
+ ? 'hybrid'
448
+ : 'roadmap';
419
449
 
420
- const gestureHandling =
421
- scrollEnabled === false && zoomEnabled === false
450
+ const gestureHandling = staticMode
451
+ ? 'none'
452
+ : scrollEnabled === false && zoomEnabled === false
422
453
  ? 'none'
423
454
  : scrollEnabled === false
424
455
  ? 'cooperative'
425
456
  : 'auto';
426
457
 
427
- const colorScheme =
428
- theme === 'dark'
429
- ? ColorScheme.DARK
430
- : theme === 'light'
431
- ? ColorScheme.LIGHT
432
- : ColorScheme.FOLLOW_SYSTEM;
433
-
434
- const defaultCenter = initialCoordinate
435
- ? { lat: initialCoordinate.latitude, lng: initialCoordinate.longitude }
436
- : undefined;
437
-
438
- return (
439
- <MapContext.Provider
440
- value={{
441
- map,
442
- isDragging,
443
- moveCamera: panToCoordinate,
444
- onCalloutClose,
445
- closeCallouts,
446
- }}
447
- >
448
- <View ref={containerRef} style={style}>
449
- <Map
450
- id={id}
451
- mapId={mapId}
452
- defaultCenter={defaultCenter}
453
- defaultZoom={initialZoom}
454
- minZoom={minZoom}
455
- maxZoom={maxZoom}
456
- gestureHandling={gestureHandling}
457
- colorScheme={colorScheme}
458
- disableDefaultUI
459
- isFractionalZoomEnabled
460
- tilt={pitchEnabled === false ? 0 : undefined}
461
- onClick={handleClick}
462
- onDragstart={handleDragStart}
463
- onDragend={handleDragEnd}
464
- onCameraChanged={handleCameraChanged}
465
- onIdle={handleIdle}
466
- >
467
- <UserLocationMarker enabled={userLocationEnabled} />
468
- {children}
469
- </Map>
470
- </View>
471
- </MapContext.Provider>
472
- );
473
- });
458
+ const colorScheme =
459
+ theme === 'dark'
460
+ ? ColorScheme.DARK
461
+ : theme === 'light'
462
+ ? ColorScheme.LIGHT
463
+ : ColorScheme.FOLLOW_SYSTEM;
464
+
465
+ const defaultCenter = initialCoordinate
466
+ ? { lat: initialCoordinate.latitude, lng: initialCoordinate.longitude }
467
+ : undefined;
468
+
469
+ return (
470
+ <MapContext.Provider
471
+ value={useMemo(
472
+ () => ({
473
+ map,
474
+ isDraggingRef,
475
+ moveCamera: panToCoordinate,
476
+ onCalloutClose,
477
+ closeCallouts,
478
+ }),
479
+ [map, panToCoordinate, onCalloutClose, closeCallouts]
480
+ )}
481
+ >
482
+ <View ref={containerRef} style={style}>
483
+ <Map
484
+ id={id}
485
+ mapId={mapId}
486
+ defaultCenter={defaultCenter}
487
+ defaultZoom={initialZoom}
488
+ minZoom={minZoom}
489
+ maxZoom={maxZoom}
490
+ mapTypeId={mapTypeId}
491
+ gestureHandling={gestureHandling}
492
+ colorScheme={colorScheme}
493
+ disableDefaultUI
494
+ rotateControl={staticMode ? false : compassEnabled}
495
+ clickableIcons={!staticMode}
496
+ keyboardShortcuts={!staticMode}
497
+ isFractionalZoomEnabled
498
+ tilt={pitchEnabled === false ? 0 : undefined}
499
+ onClick={staticMode ? undefined : handleClick}
500
+ onDragstart={handleDragStart}
501
+ onDragend={handleDragEnd}
502
+ onCameraChanged={handleCameraChanged}
503
+ onIdle={handleIdle}
504
+ >
505
+ <UserLocationMarker enabled={userLocationEnabled} />
506
+ {children}
507
+ </Map>
508
+ </View>
509
+ </MapContext.Provider>
510
+ );
511
+ })
512
+ );