@maydon_tech/react-native-nitro-maps 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/LICENSE +20 -0
  2. package/NitroMap.podspec +42 -0
  3. package/README.md +172 -0
  4. package/android/CMakeLists.txt +27 -0
  5. package/android/build.gradle +141 -0
  6. package/android/gradle.properties +5 -0
  7. package/android/src/main/AndroidManifest.xml +3 -0
  8. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  9. package/android/src/main/java/com/margelo/nitro/nitromap/ClusterIconGenerator.kt +108 -0
  10. package/android/src/main/java/com/margelo/nitro/nitromap/ColorUtils.kt +63 -0
  11. package/android/src/main/java/com/margelo/nitro/nitromap/HybridNitroMap.kt +408 -0
  12. package/android/src/main/java/com/margelo/nitro/nitromap/HybridNitroMapConfig.kt +68 -0
  13. package/android/src/main/java/com/margelo/nitro/nitromap/MarkerIconCache.kt +176 -0
  14. package/android/src/main/java/com/margelo/nitro/nitromap/MarkerIconFactory.kt +252 -0
  15. package/android/src/main/java/com/margelo/nitro/nitromap/NitroMapPackage.kt +33 -0
  16. package/android/src/main/java/com/margelo/nitro/nitromap/clustering/NitroClusterEngine.kt +252 -0
  17. package/android/src/main/java/com/margelo/nitro/nitromap/clustering/QuadTree.kt +195 -0
  18. package/android/src/main/java/com/margelo/nitro/nitromap/providers/GoogleMapProvider.kt +912 -0
  19. package/android/src/main/java/com/margelo/nitro/nitromap/providers/MapProviderInterface.kt +70 -0
  20. package/cpp/ClusterEngine.hpp +411 -0
  21. package/cpp/KDBush.hpp +238 -0
  22. package/cpp/QuadTree.hpp +246 -0
  23. package/ios/Clustering/ClusterEngineWrapper.h +58 -0
  24. package/ios/Clustering/ClusterEngineWrapper.mm +142 -0
  25. package/ios/Clustering/ClusterIconRenderer.swift +80 -0
  26. package/ios/Clustering/NitroClusterEngine.swift +117 -0
  27. package/ios/Clustering/NitroClusterIconGenerator.swift +35 -0
  28. package/ios/MarkerRenderer/MarkerIconFactory.swift +322 -0
  29. package/ios/MarkerRenderer/PriceMarkerRenderer.swift +140 -0
  30. package/ios/NitroMap.swift +332 -0
  31. package/ios/NitroMapConfig/HybridNitroMapConfig.swift +33 -0
  32. package/ios/Providers/GoogleMapDelegate.swift +310 -0
  33. package/ios/Providers/GoogleMapProvider+Camera.swift +164 -0
  34. package/ios/Providers/GoogleMapProvider.swift +924 -0
  35. package/ios/Providers/MapProviderProtocol.swift +78 -0
  36. package/ios/Shared/ClusterConfig+Factory.swift +58 -0
  37. package/ios/Shared/ClusteringManager.swift +211 -0
  38. package/ios/Shared/MapStyleProvider.swift +135 -0
  39. package/ios/Shared/MarkerSelectionHandler.swift +116 -0
  40. package/ios/Utils/ColorValueExtension.swift +54 -0
  41. package/lib/module/components/ImageMarker.js +146 -0
  42. package/lib/module/components/ImageMarker.js.map +1 -0
  43. package/lib/module/components/NitroMap.js +320 -0
  44. package/lib/module/components/NitroMap.js.map +1 -0
  45. package/lib/module/components/PriceMarker.js +165 -0
  46. package/lib/module/components/PriceMarker.js.map +1 -0
  47. package/lib/module/context/NitroMapContext.js +15 -0
  48. package/lib/module/context/NitroMapContext.js.map +1 -0
  49. package/lib/module/hooks/useNitroMarker.js +104 -0
  50. package/lib/module/hooks/useNitroMarker.js.map +1 -0
  51. package/lib/module/index.js +21 -0
  52. package/lib/module/index.js.map +1 -0
  53. package/lib/module/modules/index.js +4 -0
  54. package/lib/module/modules/index.js.map +1 -0
  55. package/lib/module/modules/module.js +30 -0
  56. package/lib/module/modules/module.js.map +1 -0
  57. package/lib/module/package.json +1 -0
  58. package/lib/module/specs/NitroMap.nitro.js +4 -0
  59. package/lib/module/specs/NitroMap.nitro.js.map +1 -0
  60. package/lib/module/specs/NitroMapConfig.nitro.js +4 -0
  61. package/lib/module/specs/NitroMapConfig.nitro.js.map +1 -0
  62. package/lib/module/types/map.js +2 -0
  63. package/lib/module/types/map.js.map +1 -0
  64. package/lib/module/types/marker.js +4 -0
  65. package/lib/module/types/marker.js.map +1 -0
  66. package/lib/module/utils/colors.js +147 -0
  67. package/lib/module/utils/colors.js.map +1 -0
  68. package/lib/typescript/package.json +1 -0
  69. package/lib/typescript/src/components/ImageMarker.d.ts +70 -0
  70. package/lib/typescript/src/components/ImageMarker.d.ts.map +1 -0
  71. package/lib/typescript/src/components/NitroMap.d.ts +14 -0
  72. package/lib/typescript/src/components/NitroMap.d.ts.map +1 -0
  73. package/lib/typescript/src/components/PriceMarker.d.ts +88 -0
  74. package/lib/typescript/src/components/PriceMarker.d.ts.map +1 -0
  75. package/lib/typescript/src/context/NitroMapContext.d.ts +16 -0
  76. package/lib/typescript/src/context/NitroMapContext.d.ts.map +1 -0
  77. package/lib/typescript/src/hooks/useNitroMarker.d.ts +78 -0
  78. package/lib/typescript/src/hooks/useNitroMarker.d.ts.map +1 -0
  79. package/lib/typescript/src/index.d.ts +12 -0
  80. package/lib/typescript/src/index.d.ts.map +1 -0
  81. package/lib/typescript/src/modules/index.d.ts +2 -0
  82. package/lib/typescript/src/modules/index.d.ts.map +1 -0
  83. package/lib/typescript/src/modules/module.d.ts +22 -0
  84. package/lib/typescript/src/modules/module.d.ts.map +1 -0
  85. package/lib/typescript/src/specs/NitroMap.nitro.d.ts +227 -0
  86. package/lib/typescript/src/specs/NitroMap.nitro.d.ts.map +1 -0
  87. package/lib/typescript/src/specs/NitroMapConfig.nitro.d.ts +10 -0
  88. package/lib/typescript/src/specs/NitroMapConfig.nitro.d.ts.map +1 -0
  89. package/lib/typescript/src/types/map.d.ts +154 -0
  90. package/lib/typescript/src/types/map.d.ts.map +1 -0
  91. package/lib/typescript/src/types/marker.d.ts +248 -0
  92. package/lib/typescript/src/types/marker.d.ts.map +1 -0
  93. package/lib/typescript/src/utils/colors.d.ts +82 -0
  94. package/lib/typescript/src/utils/colors.d.ts.map +1 -0
  95. package/nitro.json +21 -0
  96. package/nitrogen/generated/android/c++/JCamera.hpp +74 -0
  97. package/nitrogen/generated/android/c++/JClusterAnimationStyle.hpp +68 -0
  98. package/nitrogen/generated/android/c++/JClusterConfig.hpp +121 -0
  99. package/nitrogen/generated/android/c++/JClusterPressEvent.hpp +86 -0
  100. package/nitrogen/generated/android/c++/JClusterStrategy.hpp +59 -0
  101. package/nitrogen/generated/android/c++/JColorValue.cpp +26 -0
  102. package/nitrogen/generated/android/c++/JColorValue.hpp +70 -0
  103. package/nitrogen/generated/android/c++/JCoordinate.hpp +61 -0
  104. package/nitrogen/generated/android/c++/JEdgePadding.hpp +69 -0
  105. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  106. package/nitrogen/generated/android/c++/JFunc_void_ClusterPressEvent.hpp +81 -0
  107. package/nitrogen/generated/android/c++/JFunc_void_MapError.hpp +78 -0
  108. package/nitrogen/generated/android/c++/JFunc_void_MapPressEvent.hpp +81 -0
  109. package/nitrogen/generated/android/c++/JFunc_void_MarkerDragEvent.hpp +80 -0
  110. package/nitrogen/generated/android/c++/JFunc_void_MarkerPressEvent.hpp +80 -0
  111. package/nitrogen/generated/android/c++/JFunc_void_RegionChangeEvent.hpp +79 -0
  112. package/nitrogen/generated/android/c++/JHybridNitroMapConfigSpec.cpp +59 -0
  113. package/nitrogen/generated/android/c++/JHybridNitroMapConfigSpec.hpp +66 -0
  114. package/nitrogen/generated/android/c++/JHybridNitroMapSpec.cpp +593 -0
  115. package/nitrogen/generated/android/c++/JHybridNitroMapSpec.hpp +125 -0
  116. package/nitrogen/generated/android/c++/JImageMarkerConfig.hpp +86 -0
  117. package/nitrogen/generated/android/c++/JMapBoundaries.hpp +62 -0
  118. package/nitrogen/generated/android/c++/JMapError.hpp +61 -0
  119. package/nitrogen/generated/android/c++/JMapPressEvent.hpp +64 -0
  120. package/nitrogen/generated/android/c++/JMapProvider.hpp +62 -0
  121. package/nitrogen/generated/android/c++/JMapStyleElement.hpp +87 -0
  122. package/nitrogen/generated/android/c++/JMapStyler.hpp +78 -0
  123. package/nitrogen/generated/android/c++/JMapType.hpp +62 -0
  124. package/nitrogen/generated/android/c++/JMarkerAnimation.hpp +62 -0
  125. package/nitrogen/generated/android/c++/JMarkerColor.hpp +69 -0
  126. package/nitrogen/generated/android/c++/JMarkerConfig.hpp +77 -0
  127. package/nitrogen/generated/android/c++/JMarkerData.hpp +121 -0
  128. package/nitrogen/generated/android/c++/JMarkerDragEvent.hpp +63 -0
  129. package/nitrogen/generated/android/c++/JMarkerPressEvent.hpp +63 -0
  130. package/nitrogen/generated/android/c++/JMarkerStyle.hpp +62 -0
  131. package/nitrogen/generated/android/c++/JPoint.hpp +61 -0
  132. package/nitrogen/generated/android/c++/JPriceMarkerStyle.hpp +102 -0
  133. package/nitrogen/generated/android/c++/JRegion.hpp +69 -0
  134. package/nitrogen/generated/android/c++/JRegionChangeEvent.hpp +62 -0
  135. package/nitrogen/generated/android/c++/JVariant_String_MarkerColor.cpp +26 -0
  136. package/nitrogen/generated/android/c++/JVariant_String_MarkerColor.hpp +70 -0
  137. package/nitrogen/generated/android/c++/views/JHybridNitroMapStateUpdater.cpp +144 -0
  138. package/nitrogen/generated/android/c++/views/JHybridNitroMapStateUpdater.hpp +49 -0
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Camera.kt +50 -0
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterAnimationStyle.kt +24 -0
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterConfig.kt +80 -0
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterPressEvent.kt +44 -0
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterStrategy.kt +21 -0
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ColorValue.kt +59 -0
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Coordinate.kt +41 -0
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/EdgePadding.kt +47 -0
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void.kt +80 -0
  148. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_ClusterPressEvent.kt +80 -0
  149. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MapError.kt +80 -0
  150. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MapPressEvent.kt +80 -0
  151. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MarkerDragEvent.kt +80 -0
  152. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MarkerPressEvent.kt +80 -0
  153. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_RegionChangeEvent.kt +80 -0
  154. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/HybridNitroMapConfigSpec.kt +61 -0
  155. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/HybridNitroMapSpec.kt +342 -0
  156. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ImageMarkerConfig.kt +56 -0
  157. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapBoundaries.kt +41 -0
  158. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapError.kt +41 -0
  159. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapPressEvent.kt +41 -0
  160. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapProvider.kt +22 -0
  161. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapStyleElement.kt +44 -0
  162. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapStyler.kt +53 -0
  163. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapType.kt +22 -0
  164. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerAnimation.kt +22 -0
  165. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerColor.kt +47 -0
  166. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerConfig.kt +44 -0
  167. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerData.kt +71 -0
  168. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerDragEvent.kt +41 -0
  169. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerPressEvent.kt +41 -0
  170. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerStyle.kt +22 -0
  171. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Point.kt +41 -0
  172. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/PriceMarkerStyle.kt +68 -0
  173. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Region.kt +47 -0
  174. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/RegionChangeEvent.kt +41 -0
  175. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Variant_String_MarkerColor.kt +59 -0
  176. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/nitromapOnLoad.kt +35 -0
  177. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/views/HybridNitroMapManager.kt +50 -0
  178. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/views/HybridNitroMapStateUpdater.kt +23 -0
  179. package/nitrogen/generated/android/nitromap+autolinking.cmake +87 -0
  180. package/nitrogen/generated/android/nitromap+autolinking.gradle +27 -0
  181. package/nitrogen/generated/android/nitromapOnLoad.cpp +70 -0
  182. package/nitrogen/generated/android/nitromapOnLoad.hpp +25 -0
  183. package/nitrogen/generated/ios/NitroMap+autolinking.rb +60 -0
  184. package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Bridge.cpp +130 -0
  185. package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Bridge.hpp +793 -0
  186. package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Umbrella.hpp +132 -0
  187. package/nitrogen/generated/ios/NitroMapAutolinking.mm +41 -0
  188. package/nitrogen/generated/ios/NitroMapAutolinking.swift +40 -0
  189. package/nitrogen/generated/ios/c++/HybridNitroMapConfigSpecSwift.cpp +11 -0
  190. package/nitrogen/generated/ios/c++/HybridNitroMapConfigSpecSwift.hpp +84 -0
  191. package/nitrogen/generated/ios/c++/HybridNitroMapSpecSwift.cpp +11 -0
  192. package/nitrogen/generated/ios/c++/HybridNitroMapSpecSwift.hpp +410 -0
  193. package/nitrogen/generated/ios/c++/views/HybridNitroMapComponent.mm +206 -0
  194. package/nitrogen/generated/ios/swift/Camera.swift +80 -0
  195. package/nitrogen/generated/ios/swift/ClusterAnimationStyle.swift +52 -0
  196. package/nitrogen/generated/ios/swift/ClusterConfig.swift +268 -0
  197. package/nitrogen/generated/ios/swift/ClusterPressEvent.swift +70 -0
  198. package/nitrogen/generated/ios/swift/ClusterStrategy.swift +40 -0
  199. package/nitrogen/generated/ios/swift/ColorValue.swift +18 -0
  200. package/nitrogen/generated/ios/swift/Coordinate.swift +47 -0
  201. package/nitrogen/generated/ios/swift/EdgePadding.swift +69 -0
  202. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  203. package/nitrogen/generated/ios/swift/Func_void_Camera.swift +47 -0
  204. package/nitrogen/generated/ios/swift/Func_void_ClusterPressEvent.swift +47 -0
  205. package/nitrogen/generated/ios/swift/Func_void_MapBoundaries.swift +47 -0
  206. package/nitrogen/generated/ios/swift/Func_void_MapError.swift +47 -0
  207. package/nitrogen/generated/ios/swift/Func_void_MapPressEvent.swift +47 -0
  208. package/nitrogen/generated/ios/swift/Func_void_MarkerDragEvent.swift +47 -0
  209. package/nitrogen/generated/ios/swift/Func_void_MarkerPressEvent.swift +47 -0
  210. package/nitrogen/generated/ios/swift/Func_void_RegionChangeEvent.swift +47 -0
  211. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  212. package/nitrogen/generated/ios/swift/HybridNitroMapConfigSpec.swift +57 -0
  213. package/nitrogen/generated/ios/swift/HybridNitroMapConfigSpec_cxx.swift +142 -0
  214. package/nitrogen/generated/ios/swift/HybridNitroMapSpec.swift +93 -0
  215. package/nitrogen/generated/ios/swift/HybridNitroMapSpec_cxx.swift +953 -0
  216. package/nitrogen/generated/ios/swift/ImageMarkerConfig.swift +166 -0
  217. package/nitrogen/generated/ios/swift/MapBoundaries.swift +47 -0
  218. package/nitrogen/generated/ios/swift/MapError.swift +47 -0
  219. package/nitrogen/generated/ios/swift/MapPressEvent.swift +47 -0
  220. package/nitrogen/generated/ios/swift/MapProvider.swift +44 -0
  221. package/nitrogen/generated/ios/swift/MapStyleElement.swift +108 -0
  222. package/nitrogen/generated/ios/swift/MapStyler.swift +177 -0
  223. package/nitrogen/generated/ios/swift/MapType.swift +44 -0
  224. package/nitrogen/generated/ios/swift/MarkerAnimation.swift +44 -0
  225. package/nitrogen/generated/ios/swift/MarkerColor.swift +69 -0
  226. package/nitrogen/generated/ios/swift/MarkerConfig.swift +82 -0
  227. package/nitrogen/generated/ios/swift/MarkerData.swift +195 -0
  228. package/nitrogen/generated/ios/swift/MarkerDragEvent.swift +47 -0
  229. package/nitrogen/generated/ios/swift/MarkerPressEvent.swift +47 -0
  230. package/nitrogen/generated/ios/swift/MarkerStyle.swift +44 -0
  231. package/nitrogen/generated/ios/swift/Point.swift +47 -0
  232. package/nitrogen/generated/ios/swift/PriceMarkerStyle.swift +374 -0
  233. package/nitrogen/generated/ios/swift/Region.swift +69 -0
  234. package/nitrogen/generated/ios/swift/RegionChangeEvent.swift +47 -0
  235. package/nitrogen/generated/ios/swift/Variant_String_MarkerColor.swift +18 -0
  236. package/nitrogen/generated/shared/c++/Camera.hpp +92 -0
  237. package/nitrogen/generated/shared/c++/ClusterAnimationStyle.hpp +88 -0
  238. package/nitrogen/generated/shared/c++/ClusterConfig.hpp +140 -0
  239. package/nitrogen/generated/shared/c++/ClusterPressEvent.hpp +86 -0
  240. package/nitrogen/generated/shared/c++/ClusterStrategy.hpp +76 -0
  241. package/nitrogen/generated/shared/c++/Coordinate.hpp +79 -0
  242. package/nitrogen/generated/shared/c++/EdgePadding.hpp +87 -0
  243. package/nitrogen/generated/shared/c++/HybridNitroMapConfigSpec.cpp +22 -0
  244. package/nitrogen/generated/shared/c++/HybridNitroMapConfigSpec.hpp +65 -0
  245. package/nitrogen/generated/shared/c++/HybridNitroMapSpec.cpp +82 -0
  246. package/nitrogen/generated/shared/c++/HybridNitroMapSpec.hpp +173 -0
  247. package/nitrogen/generated/shared/c++/ImageMarkerConfig.hpp +103 -0
  248. package/nitrogen/generated/shared/c++/MapBoundaries.hpp +80 -0
  249. package/nitrogen/generated/shared/c++/MapError.hpp +79 -0
  250. package/nitrogen/generated/shared/c++/MapPressEvent.hpp +83 -0
  251. package/nitrogen/generated/shared/c++/MapProvider.hpp +80 -0
  252. package/nitrogen/generated/shared/c++/MapStyleElement.hpp +87 -0
  253. package/nitrogen/generated/shared/c++/MapStyler.hpp +96 -0
  254. package/nitrogen/generated/shared/c++/MapType.hpp +80 -0
  255. package/nitrogen/generated/shared/c++/MarkerAnimation.hpp +80 -0
  256. package/nitrogen/generated/shared/c++/MarkerColor.hpp +87 -0
  257. package/nitrogen/generated/shared/c++/MarkerConfig.hpp +91 -0
  258. package/nitrogen/generated/shared/c++/MarkerData.hpp +131 -0
  259. package/nitrogen/generated/shared/c++/MarkerDragEvent.hpp +81 -0
  260. package/nitrogen/generated/shared/c++/MarkerPressEvent.hpp +81 -0
  261. package/nitrogen/generated/shared/c++/MarkerStyle.hpp +80 -0
  262. package/nitrogen/generated/shared/c++/Point.hpp +79 -0
  263. package/nitrogen/generated/shared/c++/PriceMarkerStyle.hpp +119 -0
  264. package/nitrogen/generated/shared/c++/Region.hpp +87 -0
  265. package/nitrogen/generated/shared/c++/RegionChangeEvent.hpp +80 -0
  266. package/nitrogen/generated/shared/c++/views/HybridNitroMapComponent.cpp +351 -0
  267. package/nitrogen/generated/shared/c++/views/HybridNitroMapComponent.hpp +141 -0
  268. package/nitrogen/generated/shared/json/NitroMapConfig.json +32 -0
  269. package/package.json +176 -0
  270. package/react-native.config.js +16 -0
  271. package/src/components/ImageMarker.tsx +254 -0
  272. package/src/components/NitroMap.tsx +433 -0
  273. package/src/components/PriceMarker.tsx +311 -0
  274. package/src/context/NitroMapContext.tsx +33 -0
  275. package/src/hooks/useNitroMarker.ts +198 -0
  276. package/src/index.tsx +62 -0
  277. package/src/modules/index.ts +6 -0
  278. package/src/modules/module.ts +45 -0
  279. package/src/specs/NitroMap.nitro.ts +292 -0
  280. package/src/specs/NitroMapConfig.nitro.ts +8 -0
  281. package/src/types/map.ts +166 -0
  282. package/src/types/marker.ts +267 -0
  283. package/src/utils/colors.ts +159 -0
@@ -0,0 +1,78 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ /// Protocol that all map providers must implement
5
+ /// This allows the library to support multiple map backends (Google, Apple, Yandex)
6
+ protocol MapProviderProtocol: AnyObject {
7
+
8
+ // MARK: - View
9
+
10
+ /// The underlying map view to be displayed
11
+ var mapView: UIView { get }
12
+
13
+ // MARK: - Properties
14
+
15
+ var initialRegion: Region? { get set }
16
+ var showsUserLocation: Bool? { get set }
17
+ var zoomEnabled: Bool? { get set }
18
+ var scrollEnabled: Bool? { get set }
19
+ var rotateEnabled: Bool? { get set }
20
+ var pitchEnabled: Bool? { get set }
21
+ var mapType: MapType? { get set }
22
+ var showsMyLocationButton: Bool? { get set }
23
+ var clusterConfig: ClusterConfig? { get set }
24
+ var customMapStyle: [MapStyleElement]? { get set }
25
+ var darkMode: Bool? { get set }
26
+
27
+ // MARK: - Callbacks
28
+
29
+ var onPress: ((MapPressEvent) -> Void)? { get set }
30
+ var onLongPress: ((MapPressEvent) -> Void)? { get set }
31
+ var onMapReady: (() -> Void)? { get set }
32
+ var onRegionChange: ((RegionChangeEvent) -> Void)? { get set }
33
+ var onRegionChangeComplete: ((RegionChangeEvent) -> Void)? { get set }
34
+ var onMarkerPress: ((MarkerPressEvent) -> Void)? { get set }
35
+ var onMarkerDragStart: ((MarkerDragEvent) -> Void)? { get set }
36
+ var onMarkerDrag: ((MarkerDragEvent) -> Void)? { get set }
37
+ var onMarkerDragEnd: ((MarkerDragEvent) -> Void)? { get set }
38
+ var onClusterPress: ((ClusterPressEvent) -> Void)? { get set }
39
+ var onError: ((MapError) -> Void)? { get set }
40
+
41
+ // MARK: - Lifecycle
42
+
43
+ func setup()
44
+ func updateSettings()
45
+
46
+ // MARK: - Camera Methods
47
+
48
+ func animateToRegion(_ region: Region, duration: Double?)
49
+ func fitToCoordinates(_ coordinates: [Coordinate], edgePadding: EdgePadding?, animated: Bool?)
50
+ func animateCamera(_ camera: Camera, duration: Double?)
51
+ func setCamera(_ camera: Camera)
52
+ func getCamera() -> Camera
53
+ func getMapBoundaries() -> MapBoundaries?
54
+
55
+ // MARK: - Marker Management
56
+
57
+ func addMarker(_ marker: MarkerData)
58
+ func addMarkers(_ markers: [MarkerData])
59
+ func updateMarker(_ marker: MarkerData)
60
+ func removeMarker(_ id: String)
61
+ func clearMarkers()
62
+ func selectMarker(_ id: String)
63
+
64
+ // MARK: - Clustering
65
+
66
+ func setClusteringEnabled(_ enabled: Bool)
67
+ func refreshClusters()
68
+ func performClustering()
69
+
70
+ // MARK: - Map Style
71
+
72
+ func setMapStyle(_ style: [MapStyleElement]?)
73
+ func setDarkMode(_ enabled: Bool)
74
+
75
+ // MARK: - Region
76
+
77
+ func getCurrentRegion() -> Region
78
+ }
@@ -0,0 +1,58 @@
1
+ import Foundation
2
+
3
+ // MARK: - ClusterConfig Factory Extension
4
+
5
+ extension ClusterConfig {
6
+
7
+ /// Creates a copy with only the `enabled` field changed.
8
+ /// Eliminates boilerplate in each provider's `setClusteringEnabled()` (DRY).
9
+ static func withEnabled(
10
+ _ enabled: Bool,
11
+ existing: ClusterConfig?
12
+ ) -> ClusterConfig {
13
+ let strat: ClusterStrategy = existing?.strategy ?? .supercluster
14
+ let rad: Double = existing?.radius ?? 80
15
+ let minSize: Double = existing?.minimumClusterSize ?? 2
16
+ let mz: Double = existing?.maxZoom ?? 20
17
+ let bg: ColorValue = existing?.backgroundColor
18
+ ?? .second(MarkerColor(r: 0, g: 122, b: 255, a: 255))
19
+ let tc: ColorValue = existing?.textColor
20
+ ?? .second(MarkerColor(r: 255, g: 255, b: 255, a: 255))
21
+ let bw: Double = existing?.borderWidth ?? 2
22
+ let bc: ColorValue = existing?.borderColor
23
+ ?? .second(MarkerColor(r: 255, g: 255, b: 255, a: 255))
24
+ let anim: Bool = existing?.animatesClusters ?? true
25
+ let dur: Double = existing?.animationDuration ?? 0.3
26
+ let style: ClusterAnimationStyle = existing?.animationStyle ?? .default
27
+ let realtime: Bool = existing?.realtimeClustering ?? false
28
+ let vpPad: Double = existing?.renderBuffer ?? 0
29
+ let throttle: Double = existing?.throttleInterval ?? 150
30
+
31
+ return ClusterConfig(
32
+ enabled: enabled,
33
+ strategy: strat,
34
+ radius: rad,
35
+ minimumClusterSize: minSize,
36
+ maxZoom: mz,
37
+ backgroundColor: bg,
38
+ textColor: tc,
39
+ borderWidth: bw,
40
+ borderColor: bc,
41
+ animatesClusters: anim,
42
+ animationDuration: dur,
43
+ animationStyle: style,
44
+ realtimeClustering: realtime,
45
+ renderBuffer: vpPad,
46
+ throttleInterval: throttle
47
+ )
48
+ }
49
+ }
50
+
51
+ // MARK: - Cluster User Data
52
+
53
+ /// User data attached to cluster markers for tap handling.
54
+ /// Shared between NitroMap, GoogleMapDelegate, etc.
55
+ struct ClusterUserData {
56
+ let markerIds: [String]
57
+ let count: Int
58
+ }
@@ -0,0 +1,211 @@
1
+ import Foundation
2
+ import UIKit
3
+ import CoreLocation
4
+
5
+ // MARK: - Clustering Manager Protocol
6
+
7
+ /// Protocol defining the clustering manager interface.
8
+ /// Enables dependency injection and mocking for unit tests.
9
+ ///
10
+ /// Usage:
11
+ /// ```swift
12
+ /// class GoogleMapProvider: MapProviderProtocol {
13
+ /// private let clusteringManager: ClusteringManagerProtocol
14
+ ///
15
+ /// init(clusteringManager: ClusteringManagerProtocol = ClusteringManager()) {
16
+ /// self.clusteringManager = clusteringManager
17
+ /// }
18
+ /// }
19
+ /// ```
20
+ protocol ClusteringManagerProtocol: AnyObject {
21
+
22
+ /// Current cluster configuration
23
+ var clusterConfig: ClusterConfig? { get set }
24
+
25
+ /// Adds a marker to the clustering engine
26
+ func addMarker(_ marker: MarkerData)
27
+
28
+ /// Removes a marker by ID
29
+ func removeMarker(_ id: String)
30
+
31
+ /// Clears all markers from the engine
32
+ func clearMarkers()
33
+
34
+ /// Clusters markers using bounds-based region
35
+ func cluster(
36
+ minLat: Double,
37
+ maxLat: Double,
38
+ minLon: Double,
39
+ maxLon: Double,
40
+ zoom: Double,
41
+ mapSize: CGSize
42
+ ) -> NitroClusterEngine.ClusteringResult
43
+
44
+
45
+ /// Executes a clustering action with debouncing to prevent rapid re-clustering
46
+ func debounce(_ action: @escaping () -> Void)
47
+
48
+ /// Gets a cluster icon for the given count
49
+ func clusterIcon(forCount count: Int) -> UIImage?
50
+ }
51
+
52
+ // MARK: - Clustering Manager Implementation
53
+
54
+ /// Production implementation of ClusteringManagerProtocol.
55
+ /// Wraps the C++ NitroClusterEngine and provides a clean Swift interface.
56
+ final class ClusteringManager: ClusteringManagerProtocol {
57
+
58
+ // MARK: - Private Properties
59
+
60
+ private let engine: NitroClusterEngine
61
+ private let iconGenerator: NitroClusterIconGenerator
62
+ private var debounceTimer: Timer?
63
+ private let debounceInterval: TimeInterval
64
+
65
+ // MARK: - Protocol Properties
66
+
67
+ var clusterConfig: ClusterConfig? {
68
+ didSet {
69
+ iconGenerator.updateConfig(clusterConfig)
70
+ if let config = clusterConfig {
71
+ engine.setClusterRadius(config.radius)
72
+ engine.setMinClusterSize(Int(config.minimumClusterSize))
73
+ engine.setMaxZoom(config.maxZoom)
74
+ }
75
+ }
76
+ }
77
+
78
+ // MARK: - Initialization
79
+
80
+ /// Creates a new clustering manager with default configuration
81
+ /// - Parameters:
82
+ /// - clusterRadius: Radius for clustering in screen points (default: 80)
83
+ /// - minClusterSize: Minimum markers to form a cluster (default: 2)
84
+ /// - maxZoom: Maximum zoom level for clustering (default: 20)
85
+ /// - debounceInterval: Debounce interval in seconds (default: 0.1)
86
+ init(
87
+ clusterRadius: Double = 80.0,
88
+ minClusterSize: Int = 2,
89
+ maxZoom: Double = 20.0,
90
+ debounceInterval: TimeInterval = 0.1
91
+ ) {
92
+ self.engine = NitroClusterEngine()
93
+ self.iconGenerator = NitroClusterIconGenerator()
94
+ self.debounceInterval = debounceInterval
95
+
96
+ engine.setClusterRadius(clusterRadius)
97
+ engine.setMinClusterSize(minClusterSize)
98
+ engine.setMaxZoom(maxZoom)
99
+ }
100
+
101
+ deinit {
102
+ debounceTimer?.invalidate()
103
+ }
104
+
105
+ // MARK: - Marker Management
106
+
107
+ func addMarker(_ marker: MarkerData) {
108
+ engine.addMarker(marker)
109
+ }
110
+
111
+ func removeMarker(_ id: String) {
112
+ engine.removeMarker(id)
113
+ }
114
+
115
+ func clearMarkers() {
116
+ engine.clearMarkers()
117
+ }
118
+
119
+ // MARK: - Clustering
120
+
121
+ func cluster(
122
+ minLat: Double,
123
+ maxLat: Double,
124
+ minLon: Double,
125
+ maxLon: Double,
126
+ zoom: Double,
127
+ mapSize: CGSize
128
+ ) -> NitroClusterEngine.ClusteringResult {
129
+ return engine.clusterWithBounds(
130
+ minLat: minLat,
131
+ maxLat: maxLat,
132
+ minLon: minLon,
133
+ maxLon: maxLon,
134
+ zoom: zoom,
135
+ mapSize: mapSize
136
+ )
137
+ }
138
+
139
+ // MARK: - Debouncing
140
+
141
+ func debounce(_ action: @escaping () -> Void) {
142
+ debounceTimer?.invalidate()
143
+ debounceTimer = Timer.scheduledTimer(
144
+ withTimeInterval: debounceInterval,
145
+ repeats: false
146
+ ) { _ in
147
+ action()
148
+ }
149
+ }
150
+
151
+ // MARK: - Icon Generation
152
+
153
+ func clusterIcon(forCount count: Int) -> UIImage? {
154
+ return iconGenerator.icon(forSize: UInt(count))
155
+ }
156
+ }
157
+
158
+ // MARK: - Mock for Unit Tests
159
+
160
+ #if DEBUG
161
+ /// Mock implementation for unit testing
162
+ final class MockClusteringManager: ClusteringManagerProtocol {
163
+
164
+ var clusterConfig: ClusterConfig?
165
+
166
+ // Tracking for assertions
167
+ private(set) var addedMarkers: [MarkerData] = []
168
+ private(set) var removedMarkerIds: [String] = []
169
+ private(set) var clearMarkersCallCount = 0
170
+ private(set) var clusterCallCount = 0
171
+
172
+ // Configurable return value
173
+ var mockClusterResult: NitroClusterEngine.ClusteringResult = NitroClusterEngine.ClusteringResult(
174
+ clusters: [],
175
+ singleMarkers: []
176
+ )
177
+
178
+ func addMarker(_ marker: MarkerData) {
179
+ addedMarkers.append(marker)
180
+ }
181
+
182
+ func removeMarker(_ id: String) {
183
+ removedMarkerIds.append(id)
184
+ }
185
+
186
+ func clearMarkers() {
187
+ clearMarkersCallCount += 1
188
+ addedMarkers.removeAll()
189
+ }
190
+
191
+ func cluster(
192
+ minLat: Double,
193
+ maxLat: Double,
194
+ minLon: Double,
195
+ maxLon: Double,
196
+ zoom: Double,
197
+ mapSize: CGSize
198
+ ) -> NitroClusterEngine.ClusteringResult {
199
+ clusterCallCount += 1
200
+ return mockClusterResult
201
+ }
202
+
203
+ func debounce(_ action: @escaping () -> Void) {
204
+ action() // Execute immediately in tests
205
+ }
206
+
207
+ func clusterIcon(forCount count: Int) -> UIImage? {
208
+ return nil
209
+ }
210
+ }
211
+ #endif
@@ -0,0 +1,135 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ // MARK: - Map Style Protocol
5
+
6
+ /// Protocol for map styling utilities.
7
+ /// Provides zoom/altitude conversions and style constants.
8
+ protocol MapStyleProviding {
9
+
10
+ /// Converts lat/lon deltas to approximate zoom level
11
+ func zoomFromDeltas(latDelta: Double, lonDelta: Double) -> Double
12
+
13
+ /// Converts zoom level to approximate altitude (meters)
14
+ func altitudeFromZoom(_ zoom: Double) -> Double
15
+
16
+ /// Converts altitude to approximate zoom level
17
+ func zoomFromAltitude(_ altitude: Double) -> Double
18
+
19
+ /// Gets the dark mode JSON style for Google Maps
20
+ var googleDarkModeStyle: String { get }
21
+ }
22
+
23
+ // MARK: - Implementation
24
+
25
+ /// Production implementation of map styling utilities.
26
+ /// All methods are pure functions - thread-safe and stateless.
27
+ final class MapStyleProvider: MapStyleProviding {
28
+
29
+ // MARK: - Singleton
30
+
31
+ /// Shared instance for convenience (stateless, so safe to share)
32
+ static let shared = MapStyleProvider()
33
+
34
+ // MARK: - Constants
35
+
36
+ /// Earth's approximate circumference at equator in degrees
37
+ private let earthCircumferenceDegrees: Double = 360.0
38
+
39
+ /// Approximate altitude at zoom level 0 (meters)
40
+ private let baseAltitude: Double = 40_000_000
41
+
42
+ /// Maximum supported zoom level
43
+ private let maxZoom: Double = 21.0
44
+
45
+ /// Minimum supported zoom level
46
+ private let minZoom: Double = 0.0
47
+
48
+ // MARK: - Initialization
49
+
50
+ init() {}
51
+
52
+ // MARK: - MapStyleProviding
53
+
54
+ func zoomFromDeltas(latDelta: Double, lonDelta: Double) -> Double {
55
+ let maxDelta = max(latDelta, lonDelta)
56
+ guard maxDelta > 0 else { return maxZoom }
57
+
58
+ let zoom = log2(earthCircumferenceDegrees / maxDelta)
59
+ return clamp(zoom, min: minZoom, max: maxZoom)
60
+ }
61
+
62
+ func altitudeFromZoom(_ zoom: Double) -> Double {
63
+ let clampedZoom = clamp(zoom, min: minZoom, max: maxZoom)
64
+ return baseAltitude / pow(2, clampedZoom)
65
+ }
66
+
67
+ func zoomFromAltitude(_ altitude: Double) -> Double {
68
+ guard altitude > 0 else { return maxZoom }
69
+
70
+ let zoom = log2(baseAltitude / altitude)
71
+ return clamp(zoom, min: minZoom, max: maxZoom)
72
+ }
73
+
74
+ var googleDarkModeStyle: String {
75
+ return Self.darkModeJSON
76
+ }
77
+
78
+ // MARK: - Private Helpers
79
+
80
+ private func clamp(_ value: Double, min: Double, max: Double) -> Double {
81
+ return Swift.max(min, Swift.min(max, value))
82
+ }
83
+
84
+ // MARK: - Dark Mode Style JSON
85
+
86
+ private static let darkModeJSON = """
87
+ [
88
+ {"elementType": "geometry", "stylers": [{"color": "#242f3e"}]},
89
+ {"elementType": "labels.text.fill", "stylers": [{"color": "#746855"}]},
90
+ {"elementType": "labels.text.stroke", "stylers": [{"color": "#242f3e"}]},
91
+ {"featureType": "administrative.locality", "elementType": "labels.text.fill", "stylers": [{"color": "#d59563"}]},
92
+ {"featureType": "poi", "elementType": "labels.text.fill", "stylers": [{"color": "#d59563"}]},
93
+ {"featureType": "poi.park", "elementType": "geometry", "stylers": [{"color": "#263c3f"}]},
94
+ {"featureType": "poi.park", "elementType": "labels.text.fill", "stylers": [{"color": "#6b9a76"}]},
95
+ {"featureType": "road", "elementType": "geometry", "stylers": [{"color": "#38414e"}]},
96
+ {"featureType": "road", "elementType": "geometry.stroke", "stylers": [{"color": "#212a37"}]},
97
+ {"featureType": "road", "elementType": "labels.text.fill", "stylers": [{"color": "#9ca5b3"}]},
98
+ {"featureType": "road.highway", "elementType": "geometry", "stylers": [{"color": "#746855"}]},
99
+ {"featureType": "road.highway", "elementType": "geometry.stroke", "stylers": [{"color": "#1f2835"}]},
100
+ {"featureType": "road.highway", "elementType": "labels.text.fill", "stylers": [{"color": "#f3d19c"}]},
101
+ {"featureType": "transit", "elementType": "geometry", "stylers": [{"color": "#2f3948"}]},
102
+ {"featureType": "transit.station", "elementType": "labels.text.fill", "stylers": [{"color": "#d59563"}]},
103
+ {"featureType": "water", "elementType": "geometry", "stylers": [{"color": "#17263c"}]},
104
+ {"featureType": "water", "elementType": "labels.text.fill", "stylers": [{"color": "#515c6d"}]},
105
+ {"featureType": "water", "elementType": "labels.text.stroke", "stylers": [{"color": "#17263c"}]}
106
+ ]
107
+ """
108
+ }
109
+
110
+ // MARK: - Mock for Unit Tests
111
+
112
+ #if DEBUG
113
+ /// Mock implementation for unit testing
114
+ final class MockMapStyleProvider: MapStyleProviding {
115
+
116
+ var mockZoom: Double = 10.0
117
+ var mockAltitude: Double = 40000.0
118
+
119
+ var googleDarkModeStyle: String {
120
+ return "[]" // Empty JSON for testing
121
+ }
122
+
123
+ func zoomFromDeltas(latDelta: Double, lonDelta: Double) -> Double {
124
+ return mockZoom
125
+ }
126
+
127
+ func altitudeFromZoom(_ zoom: Double) -> Double {
128
+ return mockAltitude
129
+ }
130
+
131
+ func zoomFromAltitude(_ altitude: Double) -> Double {
132
+ return mockZoom
133
+ }
134
+ }
135
+ #endif
@@ -0,0 +1,116 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ // MARK: - Marker Selection Protocol
5
+
6
+ /// Protocol for handling marker selection state changes.
7
+ /// Enables dependency injection and clean separation of concerns.
8
+ protocol MarkerSelectionHandling {
9
+
10
+ /// Creates an updated MarkerData with the new selection state.
11
+ /// Returns nil if the marker type doesn't support visual selection (only priceMarker does).
12
+ ///
13
+ /// - Parameters:
14
+ /// - markerData: The original marker data
15
+ /// - selected: Whether the marker should be selected
16
+ /// - Returns: Updated marker data with new selection state, or nil if unsupported
17
+ func updateSelectionState(for markerData: MarkerData, selected: Bool) -> MarkerData?
18
+ }
19
+
20
+ // MARK: - Implementation
21
+
22
+ /// Production implementation of marker selection handling.
23
+ /// Thread-safe, pure function - can be used from any thread.
24
+ final class MarkerSelectionHandler: MarkerSelectionHandling {
25
+
26
+ // MARK: - Singleton
27
+
28
+ /// Shared instance for convenience (stateless, so safe to share)
29
+ static let shared = MarkerSelectionHandler()
30
+
31
+ // MARK: - Initialization
32
+
33
+ init() {}
34
+
35
+ // MARK: - MarkerSelectionHandling
36
+
37
+ func updateSelectionState(for markerData: MarkerData, selected: Bool) -> MarkerData? {
38
+ // Only priceMarker style supports visual selection state
39
+ guard markerData.config.style == .pricemarker,
40
+ let priceConfig = markerData.config.priceMarker else {
41
+ return nil
42
+ }
43
+
44
+ // Early exit if state hasn't changed
45
+ if priceConfig.selected == selected {
46
+ return nil
47
+ }
48
+
49
+ // Create updated price config with new selection state
50
+ let updatedPriceConfig = PriceMarkerStyle(
51
+ price: priceConfig.price,
52
+ currency: priceConfig.currency,
53
+ selected: selected,
54
+ backgroundColor: priceConfig.backgroundColor,
55
+ selectedBackgroundColor: priceConfig.selectedBackgroundColor,
56
+ textColor: priceConfig.textColor,
57
+ selectedTextColor: priceConfig.selectedTextColor,
58
+ fontSize: priceConfig.fontSize,
59
+ paddingHorizontal: priceConfig.paddingHorizontal,
60
+ paddingVertical: priceConfig.paddingVertical,
61
+ shadowOpacity: priceConfig.shadowOpacity
62
+ )
63
+
64
+ // Create updated config
65
+ let updatedConfig = MarkerConfig(
66
+ style: markerData.config.style,
67
+ image: markerData.config.image,
68
+ priceMarker: updatedPriceConfig
69
+ )
70
+
71
+ // Return new marker data (immutable pattern)
72
+ return MarkerData(
73
+ id: markerData.id,
74
+ coordinate: markerData.coordinate,
75
+ title: markerData.title,
76
+ description: markerData.description,
77
+ draggable: markerData.draggable,
78
+ opacity: markerData.opacity,
79
+ rotation: markerData.rotation,
80
+ zIndex: markerData.zIndex,
81
+ anchor: markerData.anchor,
82
+ config: updatedConfig,
83
+ clusteringEnabled: markerData.clusteringEnabled,
84
+ animation: markerData.animation
85
+ )
86
+ }
87
+ }
88
+
89
+ // MARK: - Mock for Unit Tests
90
+
91
+ #if DEBUG
92
+ /// Mock implementation for unit testing
93
+ final class MockMarkerSelectionHandler: MarkerSelectionHandling {
94
+
95
+ // Tracking for assertions
96
+ private(set) var updateSelectionCallCount = 0
97
+ private(set) var lastMarkerData: MarkerData?
98
+ private(set) var lastSelectedValue: Bool?
99
+
100
+ // Configurable behavior
101
+ var shouldReturnNil = false
102
+
103
+ func updateSelectionState(for markerData: MarkerData, selected: Bool) -> MarkerData? {
104
+ updateSelectionCallCount += 1
105
+ lastMarkerData = markerData
106
+ lastSelectedValue = selected
107
+
108
+ if shouldReturnNil {
109
+ return nil
110
+ }
111
+
112
+ // Use real implementation for realistic behavior
113
+ return MarkerSelectionHandler.shared.updateSelectionState(for: markerData, selected: selected)
114
+ }
115
+ }
116
+ #endif
@@ -0,0 +1,54 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ // MARK: - ColorValue Extension
5
+ // Shared extension for converting ColorValue (hex string or MarkerColor) to MarkerColor
6
+ extension ColorValue {
7
+ /// Extract MarkerColor from ColorValue, parsing hex string if needed
8
+ func toMarkerColor() -> MarkerColor {
9
+ switch self {
10
+ case .first(let hexString):
11
+ return ColorValue.parseHex(hexString)
12
+ case .second(let markerColor):
13
+ return markerColor
14
+ }
15
+ }
16
+
17
+ /// Parse hex color string to MarkerColor
18
+ private static func parseHex(_ hex: String) -> MarkerColor {
19
+ var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
20
+ hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
21
+
22
+ var rgb: UInt64 = 0
23
+ Scanner(string: hexSanitized).scanHexInt64(&rgb)
24
+
25
+ let r, g, b: Double
26
+ if hexSanitized.count == 6 {
27
+ r = Double((rgb & 0xFF0000) >> 16)
28
+ g = Double((rgb & 0x00FF00) >> 8)
29
+ b = Double(rgb & 0x0000FF)
30
+ } else if hexSanitized.count == 3 {
31
+ r = Double((rgb & 0xF00) >> 8) * 17
32
+ g = Double((rgb & 0x0F0) >> 4) * 17
33
+ b = Double(rgb & 0x00F) * 17
34
+ } else {
35
+ r = 0; g = 0; b = 0
36
+ }
37
+
38
+ return MarkerColor(r: r, g: g, b: b, a: 255)
39
+ }
40
+ }
41
+
42
+ // MARK: - UIColor Helper
43
+ extension ColorValue {
44
+ /// Convert ColorValue directly to UIColor
45
+ func toUIColor() -> UIColor {
46
+ let color = self.toMarkerColor()
47
+ return UIColor(
48
+ red: CGFloat(color.r) / 255,
49
+ green: CGFloat(color.g) / 255,
50
+ blue: CGFloat(color.b) / 255,
51
+ alpha: CGFloat(color.a) / 255
52
+ )
53
+ }
54
+ }