@maydon_tech/react-native-nitro-maps 0.1.4 → 0.2.1
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.
- package/LICENSE +1 -1
- package/NitroMap.podspec +1 -1
- package/README.md +82 -9
- package/android/CMakeLists.txt +4 -1
- package/android/build.gradle +6 -2
- package/android/gradle.properties +4 -4
- package/android/src/main/cpp/ClusterEngineJNI.cpp +198 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/NitroMap.kt +397 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/NitroMapConfig.kt +53 -0
- package/android/src/main/{java → kotlin}/com/margelo/nitro/nitromap/NitroMapPackage.kt +4 -4
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/NitroMapView.kt +73 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/UserLocationManager.kt +295 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/clustering/ClusterIconRenderer.kt +111 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/clustering/ClusteringManager.kt +104 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/clustering/NitroClusterEngine.kt +166 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/markers/MarkerIconFactory.kt +303 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/markers/MarkerSelectionHandler.kt +72 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/markers/PriceMarkerRenderer.kt +159 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/MapProviderFactory.kt +24 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/MapProviderInterface.kt +128 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/GoogleMapDelegate.kt +317 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/GoogleMapProvider+Clustering.kt +524 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/GoogleMapProvider+Markers.kt +358 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/GoogleMapProvider+Overlays.kt +272 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/GoogleMapProvider+UserLocation.kt +296 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/GoogleMapProvider.kt +815 -0
- package/android/src/main/kotlin/com/margelo/nitro/nitromap/providers/google/MarkerTagData.kt +19 -0
- package/ios/Location/NitroLocationManager.swift +116 -0
- package/ios/MarkerRenderer/MarkerIconFactory.swift +1 -3
- package/ios/MarkerRenderer/PriceMarkerRenderer.swift +10 -6
- package/ios/NitroMap.swift +279 -13
- package/ios/NitroMapConfig/NitroMapConfig.swift +45 -0
- package/ios/Providers/{GoogleMapDelegate.swift → Google/GoogleMapDelegate.swift} +48 -23
- package/ios/Providers/Google/GoogleMapProvider+Camera.swift +180 -0
- package/ios/Providers/Google/GoogleMapProvider+Clustering.swift +541 -0
- package/ios/Providers/Google/GoogleMapProvider+Markers.swift +270 -0
- package/ios/Providers/Google/GoogleMapProvider+Overlays.swift +245 -0
- package/ios/Providers/Google/GoogleMapProvider+UserLocation.swift +180 -0
- package/ios/Providers/Google/GoogleMapProvider.swift +342 -0
- package/ios/Providers/MapProviderFactory.swift +17 -0
- package/ios/Providers/MapProviderProtocol.swift +48 -1
- package/ios/Shared/ClusterConfig+Factory.swift +2 -2
- package/ios/Shared/MapStyleProvider.swift +6 -4
- package/ios/Shared/MarkerSelectionHandler.swift +4 -1
- package/ios/Utils/ColorValueExtension.swift +46 -67
- package/lib/module/components/ImageMarker.js +39 -29
- package/lib/module/components/ImageMarker.js.map +1 -1
- package/lib/module/components/Marker.js +118 -0
- package/lib/module/components/Marker.js.map +1 -0
- package/lib/module/components/NitroCircle.js +92 -0
- package/lib/module/components/NitroCircle.js.map +1 -0
- package/lib/module/components/NitroMap.js +216 -76
- package/lib/module/components/NitroMap.js.map +1 -1
- package/lib/module/components/NitroPolygon.js +137 -0
- package/lib/module/components/NitroPolygon.js.map +1 -0
- package/lib/module/components/NitroPolyline.js +115 -0
- package/lib/module/components/NitroPolyline.js.map +1 -0
- package/lib/module/components/PriceMarker.js +16 -29
- package/lib/module/components/PriceMarker.js.map +1 -1
- package/lib/module/context/NitroMapContext.js.map +1 -1
- package/lib/module/hooks/useNitroCircle.js +18 -0
- package/lib/module/hooks/useNitroCircle.js.map +1 -0
- package/lib/module/hooks/useNitroMarker.js +26 -9
- package/lib/module/hooks/useNitroMarker.js.map +1 -1
- package/lib/module/hooks/useNitroOverlay.js +59 -0
- package/lib/module/hooks/useNitroOverlay.js.map +1 -0
- package/lib/module/hooks/useNitroPolygon.js +18 -0
- package/lib/module/hooks/useNitroPolygon.js.map +1 -0
- package/lib/module/hooks/useNitroPolyline.js +18 -0
- package/lib/module/hooks/useNitroPolyline.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/overlay.js +4 -0
- package/lib/module/types/overlay.js.map +1 -0
- package/lib/module/types/theme.js +4 -0
- package/lib/module/types/theme.js.map +1 -0
- package/lib/module/utils/colors.js +41 -13
- package/lib/module/utils/colors.js.map +1 -1
- package/lib/module/utils/validation.js +45 -0
- package/lib/module/utils/validation.js.map +1 -0
- package/lib/typescript/src/components/ImageMarker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.d.ts +34 -0
- package/lib/typescript/src/components/Marker.d.ts.map +1 -0
- package/lib/typescript/src/components/NitroCircle.d.ts +70 -0
- package/lib/typescript/src/components/NitroCircle.d.ts.map +1 -0
- package/lib/typescript/src/components/NitroMap.d.ts +60 -3
- package/lib/typescript/src/components/NitroMap.d.ts.map +1 -1
- package/lib/typescript/src/components/NitroPolygon.d.ts +86 -0
- package/lib/typescript/src/components/NitroPolygon.d.ts.map +1 -0
- package/lib/typescript/src/components/NitroPolyline.d.ts +84 -0
- package/lib/typescript/src/components/NitroPolyline.d.ts.map +1 -0
- package/lib/typescript/src/components/PriceMarker.d.ts +0 -5
- package/lib/typescript/src/components/PriceMarker.d.ts.map +1 -1
- package/lib/typescript/src/context/NitroMapContext.d.ts +2 -0
- package/lib/typescript/src/context/NitroMapContext.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useNitroCircle.d.ts +7 -0
- package/lib/typescript/src/hooks/useNitroCircle.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useNitroMarker.d.ts +20 -0
- package/lib/typescript/src/hooks/useNitroMarker.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useNitroOverlay.d.ts +26 -0
- package/lib/typescript/src/hooks/useNitroOverlay.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useNitroPolygon.d.ts +7 -0
- package/lib/typescript/src/hooks/useNitroPolygon.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useNitroPolyline.d.ts +7 -0
- package/lib/typescript/src/hooks/useNitroPolyline.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +15 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/NitroMap.nitro.d.ts +248 -6
- package/lib/typescript/src/specs/NitroMap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types/map.d.ts +34 -4
- package/lib/typescript/src/types/map.d.ts.map +1 -1
- package/lib/typescript/src/types/marker.d.ts +24 -36
- package/lib/typescript/src/types/marker.d.ts.map +1 -1
- package/lib/typescript/src/types/overlay.d.ts +84 -0
- package/lib/typescript/src/types/overlay.d.ts.map +1 -0
- package/lib/typescript/src/types/theme.d.ts +93 -0
- package/lib/typescript/src/types/theme.d.ts.map +1 -0
- package/lib/typescript/src/utils/colors.d.ts +6 -8
- package/lib/typescript/src/utils/colors.d.ts.map +1 -1
- package/lib/typescript/src/utils/validation.d.ts +12 -0
- package/lib/typescript/src/utils/validation.d.ts.map +1 -0
- package/nitrogen/generated/android/c++/JCircleData.hpp +94 -0
- package/nitrogen/generated/android/c++/JClusterConfig.hpp +5 -7
- package/nitrogen/generated/android/c++/JCoordinateRing.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_UserLocationChangeEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_UserTrackingMode.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/nitrogen/generated/android/c++/JHybridNitroMapSpec.cpp +332 -21
- package/nitrogen/generated/android/c++/JHybridNitroMapSpec.hpp +53 -2
- package/nitrogen/generated/android/c++/JMarkerAnimation.hpp +3 -6
- package/nitrogen/generated/android/c++/JMarkerData.hpp +15 -3
- package/nitrogen/generated/android/c++/JPolygonData.hpp +133 -0
- package/nitrogen/generated/android/c++/JPolylineData.hpp +113 -0
- package/nitrogen/generated/android/c++/JUserLocationChangeEvent.hpp +70 -0
- package/nitrogen/generated/android/c++/JUserTrackingMode.hpp +62 -0
- package/nitrogen/generated/android/c++/views/JHybridNitroMapStateUpdater.cpp +72 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/CircleData.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterConfig.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/CoordinateRing.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_UserLocationChangeEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_UserTrackingMode.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_std__string.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/HybridNitroMapSpec.kt +228 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerAnimation.kt +1 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerData.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/PolygonData.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/PolylineData.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/UserLocationChangeEvent.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/{ClusterAnimationStyle.kt → UserTrackingMode.kt} +6 -8
- package/nitrogen/generated/android/nitromapOnLoad.cpp +6 -0
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Bridge.cpp +24 -0
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Bridge.hpp +178 -17
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Umbrella.hpp +18 -3
- package/nitrogen/generated/ios/c++/HybridNitroMapSpecSwift.hpp +252 -16
- package/nitrogen/generated/ios/c++/views/HybridNitroMapComponent.mm +90 -5
- package/nitrogen/generated/ios/swift/CircleData.swift +143 -0
- package/nitrogen/generated/ios/swift/ClusterConfig.swift +22 -15
- package/nitrogen/generated/ios/swift/CoordinateRing.swift +48 -0
- package/nitrogen/generated/ios/swift/Func_void_UserLocationChangeEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_UserTrackingMode.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridNitroMapSpec.swift +35 -1
- package/nitrogen/generated/ios/swift/HybridNitroMapSpec_cxx.swift +582 -8
- package/nitrogen/generated/ios/swift/MarkerAnimation.swift +4 -8
- package/nitrogen/generated/ios/swift/MarkerData.swift +54 -2
- package/nitrogen/generated/ios/swift/PolygonData.swift +167 -0
- package/nitrogen/generated/ios/swift/PolylineData.swift +155 -0
- package/nitrogen/generated/ios/swift/UserLocationChangeEvent.swift +69 -0
- package/nitrogen/generated/ios/swift/UserTrackingMode.swift +44 -0
- package/nitrogen/generated/shared/c++/CircleData.hpp +113 -0
- package/nitrogen/generated/shared/c++/ClusterConfig.hpp +5 -8
- package/nitrogen/generated/shared/c++/CoordinateRing.hpp +77 -0
- package/nitrogen/generated/shared/c++/HybridNitroMapSpec.cpp +53 -2
- package/nitrogen/generated/shared/c++/HybridNitroMapSpec.hpp +75 -6
- package/nitrogen/generated/shared/c++/MarkerAnimation.hpp +4 -8
- package/nitrogen/generated/shared/c++/MarkerData.hpp +14 -2
- package/nitrogen/generated/shared/c++/PolygonData.hpp +117 -0
- package/nitrogen/generated/shared/c++/PolylineData.hpp +114 -0
- package/nitrogen/generated/shared/c++/UserLocationChangeEvent.hpp +88 -0
- package/nitrogen/generated/shared/c++/UserTrackingMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/views/HybridNitroMapComponent.cpp +216 -12
- package/nitrogen/generated/shared/c++/views/HybridNitroMapComponent.hpp +23 -1
- package/nitrogen/generated/shared/json/NitroMapConfig.json +18 -1
- package/package.json +36 -5
- package/src/components/ImageMarker.tsx +58 -42
- package/src/components/Marker.tsx +161 -0
- package/src/components/NitroCircle.tsx +183 -0
- package/src/components/NitroMap.tsx +328 -78
- package/src/components/NitroPolygon.tsx +229 -0
- package/src/components/NitroPolyline.tsx +208 -0
- package/src/components/PriceMarker.tsx +23 -48
- package/src/context/NitroMapContext.tsx +4 -0
- package/src/hooks/useNitroCircle.ts +25 -0
- package/src/hooks/useNitroMarker.ts +49 -10
- package/src/hooks/useNitroOverlay.ts +68 -0
- package/src/hooks/useNitroPolygon.ts +25 -0
- package/src/hooks/useNitroPolyline.ts +25 -0
- package/src/index.tsx +28 -2
- package/src/specs/NitroMap.nitro.ts +294 -5
- package/src/types/map.ts +36 -4
- package/src/types/marker.ts +24 -44
- package/src/types/overlay.ts +87 -0
- package/src/types/theme.ts +101 -0
- package/src/utils/colors.ts +48 -16
- package/src/utils/validation.ts +69 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/ClusterIconGenerator.kt +0 -108
- package/android/src/main/java/com/margelo/nitro/nitromap/ColorUtils.kt +0 -63
- package/android/src/main/java/com/margelo/nitro/nitromap/HybridNitroMap.kt +0 -408
- package/android/src/main/java/com/margelo/nitro/nitromap/HybridNitroMapConfig.kt +0 -68
- package/android/src/main/java/com/margelo/nitro/nitromap/MarkerIconCache.kt +0 -176
- package/android/src/main/java/com/margelo/nitro/nitromap/MarkerIconFactory.kt +0 -252
- package/android/src/main/java/com/margelo/nitro/nitromap/clustering/NitroClusterEngine.kt +0 -252
- package/android/src/main/java/com/margelo/nitro/nitromap/clustering/QuadTree.kt +0 -195
- package/android/src/main/java/com/margelo/nitro/nitromap/providers/GoogleMapProvider.kt +0 -912
- package/android/src/main/java/com/margelo/nitro/nitromap/providers/MapProviderInterface.kt +0 -70
- package/cpp/QuadTree.hpp +0 -246
- package/ios/NitroMapConfig/HybridNitroMapConfig.swift +0 -33
- package/ios/Providers/GoogleMapProvider+Camera.swift +0 -164
- package/ios/Providers/GoogleMapProvider.swift +0 -924
- package/nitrogen/generated/android/c++/JClusterAnimationStyle.hpp +0 -68
- package/nitrogen/generated/ios/swift/ClusterAnimationStyle.swift +0 -52
- package/nitrogen/generated/shared/c++/ClusterAnimationStyle.hpp +0 -88
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"validAttributes": {
|
|
7
7
|
"provider": true,
|
|
8
8
|
"initialRegion": true,
|
|
9
|
+
"region": true,
|
|
9
10
|
"showsUserLocation": true,
|
|
10
11
|
"zoomEnabled": true,
|
|
11
12
|
"scrollEnabled": true,
|
|
@@ -13,9 +14,18 @@
|
|
|
13
14
|
"pitchEnabled": true,
|
|
14
15
|
"mapType": true,
|
|
15
16
|
"customMapStyle": true,
|
|
16
|
-
"showsMyLocationButton": true,
|
|
17
17
|
"clusterConfig": true,
|
|
18
|
+
"mapPadding": true,
|
|
19
|
+
"showsTraffic": true,
|
|
20
|
+
"showsBuildings": true,
|
|
21
|
+
"showsCompass": true,
|
|
22
|
+
"minZoom": true,
|
|
23
|
+
"maxZoom": true,
|
|
18
24
|
"darkMode": true,
|
|
25
|
+
"userTrackingMode": true,
|
|
26
|
+
"userLocationImage": true,
|
|
27
|
+
"userLocationSize": true,
|
|
28
|
+
"userLocationAnchor": true,
|
|
19
29
|
"onPress": true,
|
|
20
30
|
"onLongPress": true,
|
|
21
31
|
"onMapReady": true,
|
|
@@ -26,7 +36,14 @@
|
|
|
26
36
|
"onMarkerDrag": true,
|
|
27
37
|
"onMarkerDragEnd": true,
|
|
28
38
|
"onClusterPress": true,
|
|
39
|
+
"onPolylinePress": true,
|
|
40
|
+
"onPolygonPress": true,
|
|
41
|
+
"onCirclePress": true,
|
|
29
42
|
"onError": true,
|
|
43
|
+
"onUserLocationChange": true,
|
|
44
|
+
"onUserTrackingModeChange": true,
|
|
45
|
+
"onUserLocationError": true,
|
|
46
|
+
"onMapIdle": true,
|
|
30
47
|
"hybridRef": true
|
|
31
48
|
}
|
|
32
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maydon_tech/react-native-nitro-maps",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A high-performance React Native map library powered by Nitro Modules with support for Apple Maps, Google Maps, and Yandex Maps. Features native clustering, custom markers, and seamless cross-platform integration.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"typecheck": "tsc",
|
|
44
44
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
45
45
|
"test": "jest",
|
|
46
|
-
"release": "release-it --only-version"
|
|
46
|
+
"release": "release-it --only-version",
|
|
47
|
+
"prepublishOnly": "bob build && tsc"
|
|
47
48
|
},
|
|
48
49
|
"keywords": [
|
|
49
50
|
"react-native",
|
|
@@ -68,8 +69,10 @@
|
|
|
68
69
|
"@react-native/babel-preset": "0.83.0",
|
|
69
70
|
"@react-native/eslint-config": "0.83.0",
|
|
70
71
|
"@release-it/conventional-changelog": "^10.0.1",
|
|
72
|
+
"@testing-library/react-native": "^13.3.3",
|
|
71
73
|
"@types/jest": "^29.5.14",
|
|
72
74
|
"@types/react": "^19.2.0",
|
|
75
|
+
"@types/react-test-renderer": "^19",
|
|
73
76
|
"commitlint": "^19.8.1",
|
|
74
77
|
"del-cli": "^6.0.0",
|
|
75
78
|
"eslint": "^9.35.0",
|
|
@@ -83,13 +86,15 @@
|
|
|
83
86
|
"react-native": "0.83.0",
|
|
84
87
|
"react-native-builder-bob": "^0.40.17",
|
|
85
88
|
"react-native-nitro-modules": "^0.31.10",
|
|
89
|
+
"react-test-renderer": "19.2.0",
|
|
86
90
|
"release-it": "^19.0.4",
|
|
87
91
|
"turbo": "^2.5.6",
|
|
88
92
|
"typescript": "^5.9.2"
|
|
89
93
|
},
|
|
94
|
+
"react-native": "./lib/module/index.js",
|
|
90
95
|
"peerDependencies": {
|
|
91
|
-
"react": "
|
|
92
|
-
"react-native": "
|
|
96
|
+
"react": ">=18.2.0",
|
|
97
|
+
"react-native": ">=0.72.0",
|
|
93
98
|
"react-native-nitro-modules": "^0.31.10"
|
|
94
99
|
},
|
|
95
100
|
"workspaces": [
|
|
@@ -133,10 +138,36 @@
|
|
|
133
138
|
},
|
|
134
139
|
"jest": {
|
|
135
140
|
"preset": "react-native",
|
|
141
|
+
"setupFiles": [
|
|
142
|
+
"./jest.setup.js"
|
|
143
|
+
],
|
|
136
144
|
"modulePathIgnorePatterns": [
|
|
137
145
|
"<rootDir>/example/node_modules",
|
|
138
146
|
"<rootDir>/lib/"
|
|
139
|
-
]
|
|
147
|
+
],
|
|
148
|
+
"transformIgnorePatterns": [
|
|
149
|
+
"node_modules/(?!((jest-)?react-native|@react-native(-community)?|react-native-nitro-modules)/)"
|
|
150
|
+
],
|
|
151
|
+
"collectCoverageFrom": [
|
|
152
|
+
"src/utils/**/*.ts",
|
|
153
|
+
"src/hooks/**/*.ts",
|
|
154
|
+
"src/context/**/*.tsx",
|
|
155
|
+
"!src/**/*.nitro.ts"
|
|
156
|
+
],
|
|
157
|
+
"coverageThreshold": {
|
|
158
|
+
"global": {
|
|
159
|
+
"branches": 70,
|
|
160
|
+
"functions": 40,
|
|
161
|
+
"lines": 65,
|
|
162
|
+
"statements": 65
|
|
163
|
+
},
|
|
164
|
+
"./src/utils/": {
|
|
165
|
+
"branches": 90,
|
|
166
|
+
"functions": 100,
|
|
167
|
+
"lines": 90,
|
|
168
|
+
"statements": 90
|
|
169
|
+
}
|
|
170
|
+
}
|
|
140
171
|
},
|
|
141
172
|
"commitlint": {
|
|
142
173
|
"extends": [
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
// src/components/ImageMarker.tsx
|
|
2
|
-
import { memo, useCallback,
|
|
2
|
+
import { memo, useCallback, useEffect } from 'react';
|
|
3
3
|
import {
|
|
4
4
|
useNitroMarker,
|
|
5
|
+
useMarkerHandlers,
|
|
5
6
|
type CommonMarkerProps,
|
|
6
7
|
} from '../hooks/useNitroMarker';
|
|
7
|
-
import
|
|
8
|
-
|
|
8
|
+
import {
|
|
9
|
+
Colors,
|
|
10
|
+
parseColor,
|
|
11
|
+
areColorsEqual,
|
|
12
|
+
type ColorValue,
|
|
13
|
+
} from '../utils/colors';
|
|
14
|
+
|
|
15
|
+
const MAX_IMAGE_DIMENSION = 512;
|
|
16
|
+
const MIN_IMAGE_DIMENSION = 1;
|
|
17
|
+
|
|
18
|
+
/** Clamp a dimension to [1, 512] and warn in __DEV__ if clamped */
|
|
19
|
+
function clampDimension(value: number, name: string): number {
|
|
20
|
+
if (value >= MIN_IMAGE_DIMENSION && value <= MAX_IMAGE_DIMENSION)
|
|
21
|
+
return value;
|
|
22
|
+
if (__DEV__) {
|
|
23
|
+
console.warn(
|
|
24
|
+
`[ImageMarker] ${name}=${value} clamped to [${MIN_IMAGE_DIMENSION}, ${MAX_IMAGE_DIMENSION}].`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return Math.max(MIN_IMAGE_DIMENSION, Math.min(MAX_IMAGE_DIMENSION, value));
|
|
28
|
+
}
|
|
9
29
|
|
|
10
30
|
/**
|
|
11
31
|
* Props for the ImageMarker component
|
|
@@ -73,7 +93,10 @@ const arePropsEqual = (
|
|
|
73
93
|
prevProps.rotation !== nextProps.rotation ||
|
|
74
94
|
prevProps.zIndex !== nextProps.zIndex ||
|
|
75
95
|
prevProps.clusteringEnabled !== nextProps.clusteringEnabled ||
|
|
76
|
-
prevProps.animation !== nextProps.animation
|
|
96
|
+
prevProps.animation !== nextProps.animation ||
|
|
97
|
+
prevProps.animationDuration !== nextProps.animationDuration ||
|
|
98
|
+
prevProps.animateOnReappear !== nextProps.animateOnReappear ||
|
|
99
|
+
prevProps.accessibilityLabel !== nextProps.accessibilityLabel
|
|
77
100
|
) {
|
|
78
101
|
return false;
|
|
79
102
|
}
|
|
@@ -92,28 +115,7 @@ const arePropsEqual = (
|
|
|
92
115
|
return false;
|
|
93
116
|
}
|
|
94
117
|
|
|
95
|
-
|
|
96
|
-
a: ColorValue | undefined,
|
|
97
|
-
b: ColorValue | undefined
|
|
98
|
-
) => {
|
|
99
|
-
if (!a && !b) return true;
|
|
100
|
-
if (!a || !b) return false;
|
|
101
|
-
// If both are strings, compare directly
|
|
102
|
-
if (typeof a === 'string' && typeof b === 'string') return a === b;
|
|
103
|
-
// If types differ, not equal
|
|
104
|
-
if (typeof a !== typeof b) return false;
|
|
105
|
-
// Both are MarkerColor objects
|
|
106
|
-
const aColor = a as MarkerColor;
|
|
107
|
-
const bColor = b as MarkerColor;
|
|
108
|
-
return (
|
|
109
|
-
aColor.r === bColor.r &&
|
|
110
|
-
aColor.g === bColor.g &&
|
|
111
|
-
aColor.b === bColor.b &&
|
|
112
|
-
aColor.a === bColor.a
|
|
113
|
-
);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
if (!compareColors(prevProps.borderColor, nextProps.borderColor)) {
|
|
118
|
+
if (!areColorsEqual(prevProps.borderColor, nextProps.borderColor)) {
|
|
117
119
|
return false;
|
|
118
120
|
}
|
|
119
121
|
|
|
@@ -172,6 +174,9 @@ export const ImageMarker = memo(function ImageMarker({
|
|
|
172
174
|
anchor = { x: 0.5, y: 0.5 },
|
|
173
175
|
clusteringEnabled = true,
|
|
174
176
|
animation = 'none',
|
|
177
|
+
animationDuration = 0.3,
|
|
178
|
+
animateOnReappear = true,
|
|
179
|
+
accessibilityLabel,
|
|
175
180
|
|
|
176
181
|
// Events
|
|
177
182
|
onPress,
|
|
@@ -179,18 +184,23 @@ export const ImageMarker = memo(function ImageMarker({
|
|
|
179
184
|
onDrag,
|
|
180
185
|
onDragEnd,
|
|
181
186
|
}: ImageMarkerProps) {
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
187
|
+
// Dev-mode validation: at least one image source is required
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
if (__DEV__ && !imageUrl && !imageBase64) {
|
|
190
|
+
console.warn(
|
|
191
|
+
'ImageMarker: either imageUrl or imageBase64 must be provided. ' +
|
|
192
|
+
'The marker will render without an image.'
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
196
|
+
}, []);
|
|
197
|
+
|
|
198
|
+
// Clamp dimensions to safe range
|
|
199
|
+
const clampedWidth = clampDimension(width, 'width');
|
|
200
|
+
const clampedHeight = clampDimension(height, 'height');
|
|
201
|
+
|
|
202
|
+
// Memoize handlers via shared hook
|
|
203
|
+
const handlers = useMarkerHandlers(onPress, onDragStart, onDrag, onDragEnd);
|
|
194
204
|
|
|
195
205
|
// Build full marker data
|
|
196
206
|
const buildMarkerData = useCallback(
|
|
@@ -210,14 +220,17 @@ export const ImageMarker = memo(function ImageMarker({
|
|
|
210
220
|
image: {
|
|
211
221
|
imageUrl,
|
|
212
222
|
imageBase64,
|
|
213
|
-
width,
|
|
214
|
-
height,
|
|
223
|
+
width: clampedWidth,
|
|
224
|
+
height: clampedHeight,
|
|
215
225
|
cornerRadius,
|
|
216
226
|
borderWidth,
|
|
217
227
|
borderColor: parseColor(borderColor) ?? Colors.gray,
|
|
218
228
|
},
|
|
219
229
|
},
|
|
230
|
+
accessibilityLabel,
|
|
220
231
|
animation,
|
|
232
|
+
animationDuration,
|
|
233
|
+
animateOnReappear,
|
|
221
234
|
}),
|
|
222
235
|
[
|
|
223
236
|
coordinate,
|
|
@@ -231,12 +244,15 @@ export const ImageMarker = memo(function ImageMarker({
|
|
|
231
244
|
clusteringEnabled,
|
|
232
245
|
imageUrl,
|
|
233
246
|
imageBase64,
|
|
234
|
-
|
|
235
|
-
|
|
247
|
+
clampedWidth,
|
|
248
|
+
clampedHeight,
|
|
236
249
|
cornerRadius,
|
|
237
250
|
borderWidth,
|
|
238
251
|
borderColor,
|
|
252
|
+
accessibilityLabel,
|
|
239
253
|
animation,
|
|
254
|
+
animationDuration,
|
|
255
|
+
animateOnReappear,
|
|
240
256
|
]
|
|
241
257
|
);
|
|
242
258
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// src/components/Marker.tsx
|
|
2
|
+
import { memo, useCallback } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
useNitroMarker,
|
|
5
|
+
useMarkerHandlers,
|
|
6
|
+
type CommonMarkerProps,
|
|
7
|
+
} from '../hooks/useNitroMarker';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Props for the Marker component (default Google Maps pin)
|
|
11
|
+
*/
|
|
12
|
+
export type MarkerProps = CommonMarkerProps;
|
|
13
|
+
|
|
14
|
+
// ============ Custom Memo Comparison ============
|
|
15
|
+
const arePropsEqual = (
|
|
16
|
+
prevProps: MarkerProps,
|
|
17
|
+
nextProps: MarkerProps
|
|
18
|
+
): boolean => {
|
|
19
|
+
// Compare primitive props
|
|
20
|
+
if (
|
|
21
|
+
prevProps.id !== nextProps.id ||
|
|
22
|
+
prevProps.title !== nextProps.title ||
|
|
23
|
+
prevProps.description !== nextProps.description ||
|
|
24
|
+
prevProps.draggable !== nextProps.draggable ||
|
|
25
|
+
prevProps.opacity !== nextProps.opacity ||
|
|
26
|
+
prevProps.rotation !== nextProps.rotation ||
|
|
27
|
+
prevProps.zIndex !== nextProps.zIndex ||
|
|
28
|
+
prevProps.clusteringEnabled !== nextProps.clusteringEnabled ||
|
|
29
|
+
prevProps.animation !== nextProps.animation ||
|
|
30
|
+
prevProps.animationDuration !== nextProps.animationDuration ||
|
|
31
|
+
prevProps.animateOnReappear !== nextProps.animateOnReappear ||
|
|
32
|
+
prevProps.accessibilityLabel !== nextProps.accessibilityLabel
|
|
33
|
+
) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Compare coordinate
|
|
38
|
+
if (
|
|
39
|
+
prevProps.coordinate?.latitude !== nextProps.coordinate?.latitude ||
|
|
40
|
+
prevProps.coordinate?.longitude !== nextProps.coordinate?.longitude
|
|
41
|
+
) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Compare anchor
|
|
46
|
+
if (
|
|
47
|
+
prevProps.anchor?.x !== nextProps.anchor?.x ||
|
|
48
|
+
prevProps.anchor?.y !== nextProps.anchor?.y
|
|
49
|
+
) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return true;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Marker - Display the default Google Maps pin on the map
|
|
58
|
+
*
|
|
59
|
+
* The simplest marker component. Uses the standard red Google Maps pin.
|
|
60
|
+
* For custom images, use `<ImageMarker>`. For price tags, use `<PriceMarker>`.
|
|
61
|
+
*
|
|
62
|
+
* @example Basic marker
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <Marker
|
|
65
|
+
* coordinate={{ latitude: 41.29, longitude: 69.24 }}
|
|
66
|
+
* title="Hello World"
|
|
67
|
+
* description="This is a default marker"
|
|
68
|
+
* />
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example Draggable marker
|
|
72
|
+
* ```tsx
|
|
73
|
+
* <Marker
|
|
74
|
+
* coordinate={{ latitude: 41.30, longitude: 69.25 }}
|
|
75
|
+
* draggable={true}
|
|
76
|
+
* onDragEnd={(coord) => console.log('Dropped at:', coord)}
|
|
77
|
+
* />
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export const Marker = memo(function Marker({
|
|
81
|
+
// Required
|
|
82
|
+
coordinate,
|
|
83
|
+
|
|
84
|
+
// Identification
|
|
85
|
+
id,
|
|
86
|
+
|
|
87
|
+
// Common props
|
|
88
|
+
title,
|
|
89
|
+
description,
|
|
90
|
+
draggable = false,
|
|
91
|
+
opacity = 1,
|
|
92
|
+
rotation = 0,
|
|
93
|
+
zIndex = 0,
|
|
94
|
+
anchor = { x: 0.5, y: 1.0 },
|
|
95
|
+
clusteringEnabled = true,
|
|
96
|
+
animation = 'none',
|
|
97
|
+
animationDuration = 0.3,
|
|
98
|
+
animateOnReappear = true,
|
|
99
|
+
accessibilityLabel,
|
|
100
|
+
|
|
101
|
+
// Events
|
|
102
|
+
onPress,
|
|
103
|
+
onDragStart,
|
|
104
|
+
onDrag,
|
|
105
|
+
onDragEnd,
|
|
106
|
+
}: MarkerProps) {
|
|
107
|
+
// Memoize handlers via shared hook
|
|
108
|
+
const handlers = useMarkerHandlers(onPress, onDragStart, onDrag, onDragEnd);
|
|
109
|
+
|
|
110
|
+
// Build full marker data
|
|
111
|
+
const buildMarkerData = useCallback(
|
|
112
|
+
(markerId: string) => ({
|
|
113
|
+
id: markerId,
|
|
114
|
+
coordinate,
|
|
115
|
+
title,
|
|
116
|
+
description,
|
|
117
|
+
draggable,
|
|
118
|
+
opacity,
|
|
119
|
+
rotation,
|
|
120
|
+
zIndex,
|
|
121
|
+
anchor,
|
|
122
|
+
clusteringEnabled,
|
|
123
|
+
config: {
|
|
124
|
+
style: 'default' as const,
|
|
125
|
+
},
|
|
126
|
+
accessibilityLabel,
|
|
127
|
+
animation,
|
|
128
|
+
animationDuration,
|
|
129
|
+
animateOnReappear,
|
|
130
|
+
}),
|
|
131
|
+
[
|
|
132
|
+
coordinate,
|
|
133
|
+
title,
|
|
134
|
+
description,
|
|
135
|
+
draggable,
|
|
136
|
+
opacity,
|
|
137
|
+
rotation,
|
|
138
|
+
zIndex,
|
|
139
|
+
anchor,
|
|
140
|
+
clusteringEnabled,
|
|
141
|
+
accessibilityLabel,
|
|
142
|
+
animation,
|
|
143
|
+
animationDuration,
|
|
144
|
+
animateOnReappear,
|
|
145
|
+
]
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Use shared marker hook
|
|
149
|
+
useNitroMarker({
|
|
150
|
+
idPrefix: 'marker',
|
|
151
|
+
providedId: id,
|
|
152
|
+
handlers,
|
|
153
|
+
buildMarkerData,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Render nothing - marker is rendered natively
|
|
157
|
+
return null;
|
|
158
|
+
}, arePropsEqual);
|
|
159
|
+
|
|
160
|
+
export { arePropsEqual as areMarkerPropsEqual };
|
|
161
|
+
export default Marker;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// src/components/NitroCircle.tsx
|
|
2
|
+
import { memo, useCallback, useEffect, useRef } from 'react';
|
|
3
|
+
import { useNitroCircle } from '../hooks/useNitroCircle';
|
|
4
|
+
import type { Coordinate } from '../types/map';
|
|
5
|
+
import type { MarkerColor } from '../types/marker';
|
|
6
|
+
import {
|
|
7
|
+
parseColor,
|
|
8
|
+
areColorsEqual,
|
|
9
|
+
type ColorValue,
|
|
10
|
+
Colors,
|
|
11
|
+
} from '../utils/colors';
|
|
12
|
+
import { validateCoordinate } from '../utils/validation';
|
|
13
|
+
import type { CircleData } from '../types/overlay';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Props for the NitroCircle component
|
|
17
|
+
*/
|
|
18
|
+
export interface NitroCircleProps {
|
|
19
|
+
/** Unique identifier for the circle */
|
|
20
|
+
id?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Center coordinate of the circle.
|
|
24
|
+
* @required
|
|
25
|
+
*/
|
|
26
|
+
center: Coordinate;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Radius of the circle in meters.
|
|
30
|
+
* @required
|
|
31
|
+
*/
|
|
32
|
+
radius: number;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Fill color of the circle (hex string like \"#00000040\" or MarkerColor object).
|
|
36
|
+
* Use 8-char hex for alpha: "#RRGGBBAA"
|
|
37
|
+
* @default MarkerColor { r: 0, g: 0, b: 0, a: 77 } (~30% opacity black)
|
|
38
|
+
*/
|
|
39
|
+
fillColor?: ColorValue;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Stroke color of the circle border (hex string or MarkerColor object).
|
|
43
|
+
* @default '#000000'
|
|
44
|
+
*/
|
|
45
|
+
strokeColor?: ColorValue;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Stroke width of the circle border in pixels.
|
|
49
|
+
* @default 1
|
|
50
|
+
*/
|
|
51
|
+
strokeWidth?: number;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Z-index for controlling overlay stacking order.
|
|
55
|
+
* Higher values render on top.
|
|
56
|
+
* @default 0
|
|
57
|
+
*/
|
|
58
|
+
zIndex?: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether this circle responds to tap events.
|
|
62
|
+
* When true, `onCirclePress` on `<NitroMap>` fires with this circle's ID.
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
tappable?: boolean;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Accessibility label read by screen readers (VoiceOver / TalkBack).
|
|
69
|
+
*/
|
|
70
|
+
accessibilityLabel?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ID generator — monotonic counter, unique within a JS runtime session
|
|
74
|
+
let circleIdCounter = 0;
|
|
75
|
+
const generateCircleId = (): string => `circle_${++circleIdCounter}`;
|
|
76
|
+
|
|
77
|
+
// Default colors
|
|
78
|
+
const defaultFillColor: MarkerColor = { r: 0, g: 0, b: 0, a: 77 };
|
|
79
|
+
const defaultStrokeColor: MarkerColor = Colors.black;
|
|
80
|
+
|
|
81
|
+
// ============ Custom Memo Comparison ============
|
|
82
|
+
const arePropsEqual = (
|
|
83
|
+
prev: NitroCircleProps,
|
|
84
|
+
next: NitroCircleProps
|
|
85
|
+
): boolean => {
|
|
86
|
+
if (
|
|
87
|
+
prev.id !== next.id ||
|
|
88
|
+
prev.radius !== next.radius ||
|
|
89
|
+
prev.strokeWidth !== next.strokeWidth ||
|
|
90
|
+
prev.zIndex !== next.zIndex ||
|
|
91
|
+
prev.tappable !== next.tappable ||
|
|
92
|
+
prev.accessibilityLabel !== next.accessibilityLabel
|
|
93
|
+
) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Compare center
|
|
98
|
+
if (
|
|
99
|
+
prev.center.latitude !== next.center.latitude ||
|
|
100
|
+
prev.center.longitude !== next.center.longitude
|
|
101
|
+
) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!areColorsEqual(prev.fillColor, next.fillColor)) return false;
|
|
106
|
+
if (!areColorsEqual(prev.strokeColor, next.strokeColor)) return false;
|
|
107
|
+
|
|
108
|
+
return true;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* NitroCircle - Draw a circle overlay on the map
|
|
113
|
+
*
|
|
114
|
+
* @example Basic circle
|
|
115
|
+
* ```tsx
|
|
116
|
+
* <NitroCircle
|
|
117
|
+
* center={{ latitude: 41.31, longitude: 69.26 }}
|
|
118
|
+
* radius={500}
|
|
119
|
+
* fillColor="#4285F440"
|
|
120
|
+
* strokeColor="#4285F4"
|
|
121
|
+
* strokeWidth={2}
|
|
122
|
+
* />
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export const NitroCircle = memo(function NitroCircle({
|
|
126
|
+
id,
|
|
127
|
+
center,
|
|
128
|
+
radius,
|
|
129
|
+
fillColor,
|
|
130
|
+
strokeColor,
|
|
131
|
+
strokeWidth = 1,
|
|
132
|
+
zIndex = 0,
|
|
133
|
+
tappable = false,
|
|
134
|
+
accessibilityLabel,
|
|
135
|
+
}: NitroCircleProps) {
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
if (__DEV__) {
|
|
138
|
+
if (radius <= 0) {
|
|
139
|
+
console.warn(
|
|
140
|
+
'NitroCircle: radius must be a positive number. ' +
|
|
141
|
+
`Received ${radius}.`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
validateCoordinate(center, 'NitroCircle center');
|
|
145
|
+
}
|
|
146
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
const circleId = useRef(id || generateCircleId()).current;
|
|
150
|
+
|
|
151
|
+
const buildCircleData = useCallback(
|
|
152
|
+
(): CircleData => ({
|
|
153
|
+
id: circleId,
|
|
154
|
+
center,
|
|
155
|
+
radius,
|
|
156
|
+
fillColor: parseColor(fillColor) ?? defaultFillColor,
|
|
157
|
+
strokeColor: parseColor(strokeColor) ?? defaultStrokeColor,
|
|
158
|
+
strokeWidth,
|
|
159
|
+
zIndex,
|
|
160
|
+
tappable,
|
|
161
|
+
accessibilityLabel,
|
|
162
|
+
}),
|
|
163
|
+
[
|
|
164
|
+
circleId,
|
|
165
|
+
center,
|
|
166
|
+
radius,
|
|
167
|
+
fillColor,
|
|
168
|
+
strokeColor,
|
|
169
|
+
strokeWidth,
|
|
170
|
+
zIndex,
|
|
171
|
+
tappable,
|
|
172
|
+
accessibilityLabel,
|
|
173
|
+
]
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
useNitroCircle(buildCircleData);
|
|
177
|
+
|
|
178
|
+
return null;
|
|
179
|
+
},
|
|
180
|
+
arePropsEqual);
|
|
181
|
+
|
|
182
|
+
export { arePropsEqual as areCirclePropsEqual };
|
|
183
|
+
export default NitroCircle;
|