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

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 +737 -37
  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
package/README.md CHANGED
@@ -116,7 +116,10 @@ import { MapView, Marker, Polyline, Polygon } from '@lugg/maps';
116
116
  - [Marker](docs/MARKER.md) - Map markers with callout support
117
117
  - [Polyline](docs/POLYLINE.md) - Draw lines on the map
118
118
  - [Polygon](docs/POLYGON.md) - Draw filled shapes on the map
119
+ - [Circle](docs/CIRCLE.md) - Draw circular overlays on the map
119
120
  - [GeoJson](docs/GEOJSON.md) - Render GeoJSON data on the map
121
+ - [GroundOverlay](docs/GROUND_OVERLAY.md) - Display images on the map
122
+ - [TileOverlay](docs/TILE_OVERLAY.md) - Display custom tile layers on the map
120
123
 
121
124
  ## Types
122
125
 
@@ -4,19 +4,21 @@ import android.content.Context
4
4
  import android.graphics.Bitmap
5
5
  import android.graphics.Canvas
6
6
  import android.view.View
7
+ import android.view.accessibility.AccessibilityEvent
7
8
  import androidx.core.graphics.createBitmap
8
9
  import androidx.core.view.isNotEmpty
10
+ import com.facebook.react.uimanager.PointerEvents
9
11
  import com.facebook.react.views.view.ReactViewGroup
10
12
 
11
13
  class LuggCalloutView(context: Context) : ReactViewGroup(context) {
12
14
  val contentView: ReactViewGroup = ReactViewGroup(context)
13
15
  var bubbled: Boolean = true
14
- var anchorX: Float = 0.5f
16
+ var offsetX: Float = 0f
15
17
  set(value) {
16
18
  field = value
17
19
  onUpdate?.invoke()
18
20
  }
19
- var anchorY: Float = 1.0f
21
+ var offsetY: Float = 0f
20
22
  set(value) {
21
23
  field = value
22
24
  onUpdate?.invoke()
@@ -28,6 +30,7 @@ class LuggCalloutView(context: Context) : ReactViewGroup(context) {
28
30
 
29
31
  init {
30
32
  visibility = GONE
33
+ pointerEvents = PointerEvents.NONE
31
34
  }
32
35
 
33
36
  override fun addView(child: View, index: Int) {
@@ -49,6 +52,10 @@ class LuggCalloutView(context: Context) : ReactViewGroup(context) {
49
52
 
50
53
  override fun getChildAt(index: Int): View? = contentView.getChildAt(index)
51
54
 
55
+ // no-op: avoid accessibility traversal of detached callout children
56
+ override fun addChildrenForAccessibility(outChildren: ArrayList<View>) {}
57
+ override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent): Boolean = false
58
+
52
59
  fun createContentBitmap(): Bitmap? {
53
60
  var maxWidth = 0
54
61
  var maxHeight = 0
@@ -2,6 +2,7 @@ package com.luggmaps
2
2
 
3
3
  import com.facebook.react.bridge.ReadableMap
4
4
  import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.uimanager.PixelUtil.dpToPx
5
6
  import com.facebook.react.uimanager.ThemedReactContext
6
7
  import com.facebook.react.uimanager.ViewGroupManager
7
8
  import com.facebook.react.uimanager.ViewManagerDelegate
@@ -22,9 +23,9 @@ class LuggCalloutViewManager :
22
23
  view.bubbled = value
23
24
  }
24
25
 
25
- override fun setAnchor(view: LuggCalloutView, value: ReadableMap?) {
26
- view.anchorX = value?.getDouble("x")?.toFloat() ?: 0.5f
27
- view.anchorY = value?.getDouble("y")?.toFloat() ?: 1.0f
26
+ override fun setOffset(view: LuggCalloutView, value: ReadableMap?) {
27
+ view.offsetX = value?.getDouble("x")?.toFloat()?.dpToPx() ?: 0f
28
+ view.offsetY = value?.getDouble("y")?.toFloat()?.dpToPx() ?: 0f
28
29
  }
29
30
 
30
31
  override fun onDropViewInstance(view: LuggCalloutView) {
@@ -0,0 +1,85 @@
1
+ package com.luggmaps
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import com.facebook.react.views.view.ReactViewGroup
6
+ import com.google.android.gms.maps.model.Circle
7
+ import com.google.android.gms.maps.model.LatLng
8
+ import com.luggmaps.events.CirclePressEvent
9
+ import com.luggmaps.extensions.dispatchEvent
10
+
11
+ interface LuggCircleViewDelegate {
12
+ fun circleViewDidUpdate(circleView: LuggCircleView)
13
+ }
14
+
15
+ class LuggCircleView(context: Context) : ReactViewGroup(context) {
16
+ var center: LatLng = LatLng(0.0, 0.0)
17
+ private set
18
+
19
+ var radius: Double = 0.0
20
+ private set
21
+
22
+ var strokeColor: Int = Color.BLACK
23
+ private set
24
+
25
+ var fillColor: Int = Color.argb(77, 0, 0, 0)
26
+ private set
27
+
28
+ var strokeWidth: Float = 1f
29
+ private set
30
+
31
+ var zIndex: Float = 0f
32
+ private set
33
+
34
+ var tappable: Boolean = false
35
+ private set
36
+
37
+ var delegate: LuggCircleViewDelegate? = null
38
+ var circle: Circle? = null
39
+
40
+ init {
41
+ visibility = GONE
42
+ }
43
+
44
+ fun setCenter(value: LatLng) {
45
+ center = value
46
+ }
47
+
48
+ fun setRadius(value: Double) {
49
+ radius = value
50
+ }
51
+
52
+ fun setStrokeColor(color: Int) {
53
+ strokeColor = color
54
+ }
55
+
56
+ fun setFillColor(color: Int) {
57
+ fillColor = color
58
+ }
59
+
60
+ fun setStrokeWidth(width: Float) {
61
+ strokeWidth = width
62
+ }
63
+
64
+ fun setZIndex(value: Float) {
65
+ zIndex = value
66
+ }
67
+
68
+ fun setTappable(value: Boolean) {
69
+ tappable = value
70
+ }
71
+
72
+ fun emitPressEvent() {
73
+ dispatchEvent(CirclePressEvent(this))
74
+ }
75
+
76
+ fun onAfterUpdateTransaction() {
77
+ delegate?.circleViewDidUpdate(this)
78
+ }
79
+
80
+ fun onDropViewInstance() {
81
+ delegate = null
82
+ circle?.remove()
83
+ circle = null
84
+ }
85
+ }
@@ -0,0 +1,79 @@
1
+ package com.luggmaps
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+ import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.ViewGroupManager
7
+ import com.facebook.react.uimanager.ViewManagerDelegate
8
+ import com.facebook.react.uimanager.annotations.ReactProp
9
+ import com.facebook.react.viewmanagers.LuggCircleViewManagerDelegate
10
+ import com.facebook.react.viewmanagers.LuggCircleViewManagerInterface
11
+ import com.google.android.gms.maps.model.LatLng
12
+
13
+ @ReactModule(name = LuggCircleViewManager.NAME)
14
+ class LuggCircleViewManager :
15
+ ViewGroupManager<LuggCircleView>(),
16
+ LuggCircleViewManagerInterface<LuggCircleView> {
17
+ private val delegate: ViewManagerDelegate<LuggCircleView> = LuggCircleViewManagerDelegate(this)
18
+
19
+ override fun getDelegate(): ViewManagerDelegate<LuggCircleView> = delegate
20
+ override fun getName(): String = NAME
21
+ override fun createViewInstance(context: ThemedReactContext): LuggCircleView = LuggCircleView(context)
22
+
23
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> =
24
+ mapOf("topCirclePress" to mapOf("registrationName" to "onCirclePress"))
25
+
26
+ override fun onDropViewInstance(view: LuggCircleView) {
27
+ super.onDropViewInstance(view)
28
+ view.onDropViewInstance()
29
+ }
30
+
31
+ override fun onAfterUpdateTransaction(view: LuggCircleView) {
32
+ super.onAfterUpdateTransaction(view)
33
+ view.onAfterUpdateTransaction()
34
+ }
35
+
36
+ @ReactProp(name = "center")
37
+ override fun setCenter(view: LuggCircleView, value: ReadableMap?) {
38
+ value?.let { map ->
39
+ val lat = map.getDouble("latitude")
40
+ val lng = map.getDouble("longitude")
41
+ view.setCenter(LatLng(lat, lng))
42
+ }
43
+ }
44
+
45
+ @ReactProp(name = "radius", defaultDouble = 0.0)
46
+ override fun setRadius(view: LuggCircleView, value: Double) {
47
+ view.setRadius(value)
48
+ }
49
+
50
+ @ReactProp(name = "strokeColor", customType = "Color")
51
+ override fun setStrokeColor(view: LuggCircleView, value: Int?) {
52
+ view.setStrokeColor(value ?: android.graphics.Color.BLACK)
53
+ }
54
+
55
+ @ReactProp(name = "fillColor", customType = "Color")
56
+ override fun setFillColor(view: LuggCircleView, value: Int?) {
57
+ view.setFillColor(value ?: android.graphics.Color.argb(77, 0, 0, 0))
58
+ }
59
+
60
+ @ReactProp(name = "strokeWidth", defaultDouble = 1.0)
61
+ override fun setStrokeWidth(view: LuggCircleView, value: Double) {
62
+ view.setStrokeWidth(value.toFloat())
63
+ }
64
+
65
+ @ReactProp(name = "tappable")
66
+ override fun setTappable(view: LuggCircleView, value: Boolean) {
67
+ view.setTappable(value)
68
+ }
69
+
70
+ @ReactProp(name = "zIndex", defaultFloat = 0f)
71
+ override fun setZIndex(view: LuggCircleView, value: Float) {
72
+ super.setZIndex(view, value)
73
+ view.setZIndex(value)
74
+ }
75
+
76
+ companion object {
77
+ const val NAME = "LuggCircleView"
78
+ }
79
+ }
@@ -0,0 +1,81 @@
1
+ package com.luggmaps
2
+
3
+ import android.content.Context
4
+ import com.facebook.react.views.view.ReactViewGroup
5
+ import com.google.android.gms.maps.model.GroundOverlay
6
+ import com.google.android.gms.maps.model.LatLng
7
+ import com.luggmaps.events.GroundOverlayPressEvent
8
+ import com.luggmaps.extensions.dispatchEvent
9
+
10
+ interface LuggGroundOverlayViewDelegate {
11
+ fun groundOverlayViewDidUpdate(groundOverlayView: LuggGroundOverlayView)
12
+ }
13
+
14
+ class LuggGroundOverlayView(context: Context) : ReactViewGroup(context) {
15
+ var imageUri: String = ""
16
+ private set
17
+
18
+ var northeast: LatLng = LatLng(0.0, 0.0)
19
+ private set
20
+
21
+ var southwest: LatLng = LatLng(0.0, 0.0)
22
+ private set
23
+
24
+ var overlayOpacity: Float = 1f
25
+ private set
26
+
27
+ var bearing: Float = 0f
28
+ private set
29
+
30
+ var zIndex: Float = 0f
31
+ private set
32
+
33
+ var tappable: Boolean = false
34
+ private set
35
+
36
+ var delegate: LuggGroundOverlayViewDelegate? = null
37
+ var groundOverlay: GroundOverlay? = null
38
+
39
+ init {
40
+ visibility = GONE
41
+ }
42
+
43
+ fun setImageUri(value: String) {
44
+ imageUri = value
45
+ }
46
+
47
+ fun setBounds(ne: LatLng, sw: LatLng) {
48
+ northeast = ne
49
+ southwest = sw
50
+ }
51
+
52
+ fun setOverlayOpacity(value: Float) {
53
+ overlayOpacity = value
54
+ }
55
+
56
+ fun setBearing(value: Float) {
57
+ bearing = value
58
+ }
59
+
60
+ fun setZIndex(value: Float) {
61
+ zIndex = value
62
+ }
63
+
64
+ fun setTappable(value: Boolean) {
65
+ tappable = value
66
+ }
67
+
68
+ fun emitPressEvent() {
69
+ dispatchEvent(GroundOverlayPressEvent(this))
70
+ }
71
+
72
+ fun onAfterUpdateTransaction() {
73
+ delegate?.groundOverlayViewDidUpdate(this)
74
+ }
75
+
76
+ fun onDropViewInstance() {
77
+ delegate = null
78
+ groundOverlay?.remove()
79
+ groundOverlay = null
80
+ }
81
+ }
@@ -0,0 +1,82 @@
1
+ package com.luggmaps
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+ import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.ViewGroupManager
7
+ import com.facebook.react.uimanager.ViewManagerDelegate
8
+ import com.facebook.react.uimanager.annotations.ReactProp
9
+ import com.facebook.react.viewmanagers.LuggGroundOverlayViewManagerDelegate
10
+ import com.facebook.react.viewmanagers.LuggGroundOverlayViewManagerInterface
11
+ import com.google.android.gms.maps.model.LatLng
12
+
13
+ @ReactModule(name = LuggGroundOverlayViewManager.NAME)
14
+ class LuggGroundOverlayViewManager :
15
+ ViewGroupManager<LuggGroundOverlayView>(),
16
+ LuggGroundOverlayViewManagerInterface<LuggGroundOverlayView> {
17
+ private val delegate: ViewManagerDelegate<LuggGroundOverlayView> = LuggGroundOverlayViewManagerDelegate(this)
18
+
19
+ override fun getDelegate(): ViewManagerDelegate<LuggGroundOverlayView> = delegate
20
+ override fun getName(): String = NAME
21
+ override fun createViewInstance(context: ThemedReactContext): LuggGroundOverlayView = LuggGroundOverlayView(context)
22
+
23
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> =
24
+ mapOf("topGroundOverlayPress" to mapOf("registrationName" to "onGroundOverlayPress"))
25
+
26
+ override fun onDropViewInstance(view: LuggGroundOverlayView) {
27
+ super.onDropViewInstance(view)
28
+ view.onDropViewInstance()
29
+ }
30
+
31
+ override fun onAfterUpdateTransaction(view: LuggGroundOverlayView) {
32
+ super.onAfterUpdateTransaction(view)
33
+ view.onAfterUpdateTransaction()
34
+ }
35
+
36
+ @ReactProp(name = "image")
37
+ override fun setImage(view: LuggGroundOverlayView, value: String?) {
38
+ view.setImageUri(value ?: "")
39
+ }
40
+
41
+ @ReactProp(name = "bounds")
42
+ override fun setBounds(view: LuggGroundOverlayView, value: ReadableMap?) {
43
+ value?.let { map ->
44
+ val ne = map.getMap("northeast")
45
+ val sw = map.getMap("southwest")
46
+ val northeast = LatLng(
47
+ ne?.getDouble("latitude") ?: 0.0,
48
+ ne?.getDouble("longitude") ?: 0.0
49
+ )
50
+ val southwest = LatLng(
51
+ sw?.getDouble("latitude") ?: 0.0,
52
+ sw?.getDouble("longitude") ?: 0.0
53
+ )
54
+ view.setBounds(northeast, southwest)
55
+ }
56
+ }
57
+
58
+ @ReactProp(name = "opacity", defaultDouble = 1.0)
59
+ override fun setOpacity(view: LuggGroundOverlayView, value: Double) {
60
+ view.setOverlayOpacity(value.toFloat())
61
+ }
62
+
63
+ @ReactProp(name = "bearing", defaultDouble = 0.0)
64
+ override fun setBearing(view: LuggGroundOverlayView, value: Double) {
65
+ view.setBearing(value.toFloat())
66
+ }
67
+
68
+ @ReactProp(name = "tappable")
69
+ override fun setTappable(view: LuggGroundOverlayView, value: Boolean) {
70
+ view.setTappable(value)
71
+ }
72
+
73
+ @ReactProp(name = "zIndex", defaultFloat = 0f)
74
+ override fun setZIndex(view: LuggGroundOverlayView, value: Float) {
75
+ super.setZIndex(view, value)
76
+ view.setZIndex(value)
77
+ }
78
+
79
+ companion object {
80
+ const val NAME = "LuggGroundOverlayView"
81
+ }
82
+ }
@@ -1,6 +1,7 @@
1
1
  package com.luggmaps
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.content.res.Configuration
4
5
  import android.view.View
5
6
  import android.view.View.VISIBLE
6
7
  import com.facebook.react.uimanager.ThemedReactContext
@@ -58,16 +59,23 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
58
59
  private var initialLatitude: Double = 37.78
59
60
  private var initialLongitude: Double = -122.43
60
61
  private var initialZoom: Float = 14f
62
+ private var mapType: String = "standard"
61
63
  private var theme: String = "system"
62
64
  private var zoomEnabled: Boolean = true
63
65
  private var scrollEnabled: Boolean = true
64
66
  private var rotateEnabled: Boolean = true
65
67
  private var pitchEnabled: Boolean = true
68
+ private var compassEnabled: Boolean = true
69
+ private var staticMode: Boolean = false
66
70
  private var userLocationEnabled: Boolean = false
67
71
  private var userLocationButtonEnabled: Boolean = false
72
+ private var poiEnabled: Boolean = true
73
+ private var poiFilterMode: String = "including"
74
+ private var poiFilterCategories: List<String> = emptyList()
68
75
  private var minZoom: Double? = null
69
76
  private var maxZoom: Double? = null
70
77
  private var edgeInsets: EdgeInsets = EdgeInsets()
78
+ private var insetAdjustment: String = "never"
71
79
 
72
80
  // region View Lifecycle
73
81
 
@@ -78,6 +86,9 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
78
86
  is LuggMarkerView -> provider?.addMarkerView(child)
79
87
  is LuggPolylineView -> provider?.addPolylineView(child)
80
88
  is LuggPolygonView -> provider?.addPolygonView(child)
89
+ is LuggCircleView -> provider?.addCircleView(child)
90
+ is LuggGroundOverlayView -> provider?.addGroundOverlayView(child)
91
+ is LuggTileOverlayView -> provider?.addTileOverlayView(child)
81
92
  }
82
93
  }
83
94
 
@@ -87,6 +98,9 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
87
98
  is LuggMarkerView -> provider?.removeMarkerView(view)
88
99
  is LuggPolylineView -> provider?.removePolylineView(view)
89
100
  is LuggPolygonView -> provider?.removePolygonView(view)
101
+ is LuggCircleView -> provider?.removeCircleView(view)
102
+ is LuggGroundOverlayView -> provider?.removeGroundOverlayView(view)
103
+ is LuggTileOverlayView -> provider?.removeTileOverlayView(view)
90
104
  }
91
105
  super.removeViewAt(index)
92
106
  }
@@ -120,8 +134,13 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
120
134
  private fun initializeProvider() {
121
135
  if (provider != null || mapWrapperView == null) return
122
136
 
137
+ if (staticMode) {
138
+ applyStaticPlaceholder()
139
+ }
140
+
123
141
  val google = GoogleMapProvider(context)
124
142
  google.mapId = mapId
143
+ google.staticMode = staticMode
125
144
  google.delegate = this
126
145
  provider = google
127
146
 
@@ -135,10 +154,30 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
135
154
  is LuggMarkerView -> google.addMarkerView(child)
136
155
  is LuggPolylineView -> google.addPolylineView(child)
137
156
  is LuggPolygonView -> google.addPolygonView(child)
157
+ is LuggCircleView -> google.addCircleView(child)
158
+ is LuggGroundOverlayView -> google.addGroundOverlayView(child)
159
+ is LuggTileOverlayView -> google.addTileOverlayView(child)
138
160
  }
139
161
  }
140
162
  }
141
163
 
164
+ // Shown while the map loads, until the map covers it
165
+ private fun applyStaticPlaceholder() {
166
+ // A user-provided background acts as the placeholder
167
+ if (background != null) return
168
+
169
+ val isDark = when (theme) {
170
+ "dark" -> true
171
+
172
+ "light" -> false
173
+
174
+ else ->
175
+ (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
176
+ Configuration.UI_MODE_NIGHT_YES
177
+ }
178
+ mapWrapperView?.setBackgroundColor(if (isDark) COLOR_PLACEHOLDER_DARK else COLOR_PLACEHOLDER_LIGHT)
179
+ }
180
+
142
181
  // endregion
143
182
 
144
183
  // region MapProviderDelegate
@@ -172,12 +211,18 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
172
211
  provider?.setScrollEnabled(scrollEnabled)
173
212
  provider?.setRotateEnabled(rotateEnabled)
174
213
  provider?.setPitchEnabled(pitchEnabled)
214
+ provider?.setCompassEnabled(compassEnabled)
175
215
  provider?.setUserLocationEnabled(userLocationEnabled)
176
216
  provider?.setUserLocationButtonEnabled(userLocationButtonEnabled)
217
+ provider?.setMapType(mapType)
177
218
  provider?.setTheme(theme)
178
219
  minZoom?.let { provider?.setMinZoom(it) }
179
220
  maxZoom?.let { provider?.setMaxZoom(it) }
180
221
  provider?.setEdgeInsets(edgeInsets)
222
+ provider?.setInsetAdjustment(insetAdjustment)
223
+ provider?.setPoiEnabled(poiEnabled)
224
+ provider?.setPoiFilterMode(poiFilterMode)
225
+ provider?.setPoiFilterCategories(poiFilterCategories)
181
226
  }
182
227
 
183
228
  fun setProvider(value: String?) {
@@ -224,6 +269,16 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
224
269
  provider?.setPitchEnabled(enabled)
225
270
  }
226
271
 
272
+ fun setCompassEnabled(enabled: Boolean) {
273
+ if (compassEnabled == enabled) return
274
+ compassEnabled = enabled
275
+ provider?.setCompassEnabled(enabled)
276
+ }
277
+
278
+ fun setStaticMode(enabled: Boolean) {
279
+ staticMode = enabled
280
+ }
281
+
227
282
  fun setUserLocationEnabled(enabled: Boolean) {
228
283
  if (userLocationEnabled == enabled) return
229
284
  userLocationEnabled = enabled
@@ -248,12 +303,42 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
248
303
  provider?.setMaxZoom(zoom)
249
304
  }
250
305
 
306
+ fun setMapType(value: String) {
307
+ if (mapType == value) return
308
+ mapType = value
309
+ provider?.setMapType(value)
310
+ }
311
+
251
312
  fun setTheme(value: String) {
252
313
  if (theme == value) return
253
314
  theme = value
254
315
  provider?.setTheme(value)
255
316
  }
256
317
 
318
+ fun setPoiEnabled(enabled: Boolean) {
319
+ if (poiEnabled == enabled) return
320
+ poiEnabled = enabled
321
+ provider?.setPoiEnabled(enabled)
322
+ }
323
+
324
+ fun setPoiFilterMode(value: String) {
325
+ if (poiFilterMode == value) return
326
+ poiFilterMode = value
327
+ provider?.setPoiFilterMode(value)
328
+ }
329
+
330
+ fun setPoiFilterCategories(categories: List<String>) {
331
+ if (poiFilterCategories == categories) return
332
+ poiFilterCategories = categories
333
+ provider?.setPoiFilterCategories(categories)
334
+ }
335
+
336
+ fun setInsetAdjustment(value: String) {
337
+ if (insetAdjustment == value) return
338
+ insetAdjustment = value
339
+ provider?.setInsetAdjustment(value)
340
+ }
341
+
257
342
  fun setEdgeInsets(
258
343
  top: Int,
259
344
  left: Int,
@@ -287,4 +372,9 @@ class LuggMapView(private val reactContext: ThemedReactContext) :
287
372
  }
288
373
 
289
374
  // endregion
375
+
376
+ companion object {
377
+ private const val COLOR_PLACEHOLDER_LIGHT = 0xFFF2F2F7.toInt()
378
+ private const val COLOR_PLACEHOLDER_DARK = 0xFF2C2C2E.toInt()
379
+ }
290
380
  }
@@ -132,6 +132,20 @@ class LuggMapViewManager :
132
132
  view.setPitchEnabled(value)
133
133
  }
134
134
 
135
+ @ReactProp(name = "compassEnabled", defaultBoolean = true)
136
+ override fun setCompassEnabled(view: LuggMapView, value: Boolean) {
137
+ view.setCompassEnabled(value)
138
+ }
139
+
140
+ @ReactProp(name = "staticMode", defaultBoolean = false)
141
+ override fun setStaticMode(view: LuggMapView, value: Boolean) {
142
+ view.setStaticMode(value)
143
+ }
144
+
145
+ // iOS only - lite mode doesn't need snapshot caching
146
+ @ReactProp(name = "staticKey")
147
+ override fun setStaticKey(view: LuggMapView, value: String?) = Unit
148
+
135
149
  @ReactProp(name = "userLocationEnabled", defaultBoolean = false)
136
150
  override fun setUserLocationEnabled(view: LuggMapView, value: Boolean) {
137
151
  view.setUserLocationEnabled(value)
@@ -152,11 +166,42 @@ class LuggMapViewManager :
152
166
  view.setMaxZoom(value)
153
167
  }
154
168
 
169
+ @ReactProp(name = "mapType")
170
+ override fun setMapType(view: LuggMapView, value: String?) {
171
+ view.setMapType(value ?: "standard")
172
+ }
173
+
155
174
  @ReactProp(name = "theme")
156
175
  override fun setTheme(view: LuggMapView, value: String?) {
157
176
  view.setTheme(value ?: "system")
158
177
  }
159
178
 
179
+ @ReactProp(name = "poiEnabled", defaultBoolean = true)
180
+ override fun setPoiEnabled(view: LuggMapView, value: Boolean) {
181
+ view.setPoiEnabled(value)
182
+ }
183
+
184
+ @ReactProp(name = "poiFilterMode")
185
+ override fun setPoiFilterMode(view: LuggMapView, value: String?) {
186
+ view.setPoiFilterMode(value ?: "including")
187
+ }
188
+
189
+ @ReactProp(name = "poiFilterCategories")
190
+ override fun setPoiFilterCategories(view: LuggMapView, value: ReadableArray?) {
191
+ val categories = mutableListOf<String>()
192
+ value?.let { array ->
193
+ for (i in 0 until array.size()) {
194
+ array.getString(i)?.let { categories.add(it) }
195
+ }
196
+ }
197
+ view.setPoiFilterCategories(categories)
198
+ }
199
+
200
+ @ReactProp(name = "insetAdjustment")
201
+ override fun setInsetAdjustment(view: LuggMapView, value: String?) {
202
+ view.setInsetAdjustment(value ?: "never")
203
+ }
204
+
160
205
  @ReactProp(name = "edgeInsets")
161
206
  override fun setEdgeInsets(view: LuggMapView, value: ReadableMap?) {
162
207
  value?.let {
@@ -10,11 +10,30 @@ class LuggMapWrapperView(context: ThemedReactContext) : ReactViewGroup(context)
10
10
 
11
11
  var touchEventHandler: ((MotionEvent) -> Unit)? = null
12
12
 
13
+ // React Native never runs an Android layout pass on Yoga-managed views, so
14
+ // a child's requestLayout (e.g. a lite mode MapView displaying its bitmap
15
+ // once loaded) would otherwise never result in a measure/layout. Live maps
16
+ // don't need this - their GL surface renders continuously once sized.
17
+ var relayoutChildOnRequest: Boolean = false
18
+
19
+ // Invoked on layout once the view has a non-zero size, so the map
20
+ // provider can create a map sized to the view
21
+ var onLayoutReady: (() -> Unit)? = null
22
+
23
+ private val measureAndLayoutChild = Runnable { layoutChild(width, height) }
24
+
13
25
  override fun dispatchTouchEvent(event: MotionEvent): Boolean {
14
26
  touchEventHandler?.invoke(event)
15
27
  return super.dispatchTouchEvent(event)
16
28
  }
17
29
 
30
+ override fun requestLayout() {
31
+ super.requestLayout()
32
+ if (relayoutChildOnRequest) {
33
+ post(measureAndLayoutChild)
34
+ }
35
+ }
36
+
18
37
  override fun onLayout(
19
38
  changed: Boolean,
20
39
  left: Int,
@@ -23,8 +42,14 @@ class LuggMapWrapperView(context: ThemedReactContext) : ReactViewGroup(context)
23
42
  bottom: Int
24
43
  ) {
25
44
  super.onLayout(changed, left, top, right, bottom)
26
- val w = right - left
27
- val h = bottom - top
45
+ layoutChild(right - left, bottom - top)
46
+ if (right - left > 0 && bottom - top > 0) {
47
+ onLayoutReady?.invoke()
48
+ }
49
+ }
50
+
51
+ private fun layoutChild(w: Int, h: Int) {
52
+ if (w <= 0 || h <= 0) return
28
53
  getChildAt(0)?.let {
29
54
  it.measure(
30
55
  MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),