@maydon_tech/react-native-nitro-maps 0.1.4 → 0.2.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.
- package/LICENSE +1 -1
- package/NitroMap.podspec +1 -1
- package/README.md +82 -9
- package/android/CMakeLists.txt +4 -1
- 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 +135 -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 +75 -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++/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 +328 -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 +149 -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/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 +175 -17
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Umbrella.hpp +15 -3
- package/nitrogen/generated/ios/c++/HybridNitroMapSpecSwift.hpp +249 -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/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 +179 -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++/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 +114 -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 +23 -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 +77 -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
|
@@ -27,9 +27,10 @@ import type {
|
|
|
27
27
|
MarkerPressEvent,
|
|
28
28
|
MarkerColor,
|
|
29
29
|
} from '../types/marker';
|
|
30
|
-
import type { MapStyle } from '../types/map';
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
30
|
+
import type { EdgePadding, MapProvider, MapStyle } from '../types/map';
|
|
31
|
+
import type { ThemeForProvider } from '../types/theme';
|
|
32
|
+
import { IsNitroMapInitialized } from '../modules';
|
|
33
|
+
import { parseColor, areColorsEqual, Colors } from '../utils/colors';
|
|
33
34
|
|
|
34
35
|
// Re-export all types
|
|
35
36
|
export * from '../specs/NitroMap.nitro';
|
|
@@ -45,18 +46,118 @@ const NitroMapHostComponent = getHostComponent<
|
|
|
45
46
|
NitroMapMethods
|
|
46
47
|
>('NitroMap', () => NitroMapConfig);
|
|
47
48
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
// Sentinel region meaning "not set / cleared".
|
|
50
|
+
// Fabric sends `null` when a previously-set optional prop is removed from JSX,
|
|
51
|
+
// and the Nitro SDK's JSIConverter only handles `undefined`, not `null` — crash.
|
|
52
|
+
// React also strips `undefined` prop values (treats them as absent).
|
|
53
|
+
// Workaround: always pass region/initialRegion and use a sentinel with negative
|
|
54
|
+
// deltas that the native side recognizes as "no-op".
|
|
55
|
+
const REGION_UNSET = {
|
|
56
|
+
latitude: 0,
|
|
57
|
+
longitude: 0,
|
|
58
|
+
latitudeDelta: -1,
|
|
59
|
+
longitudeDelta: -1,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Default "disabled" cluster config — always passed to native so the prop is
|
|
63
|
+
// never removed (same Fabric null workaround as REGION_UNSET).
|
|
64
|
+
const CLUSTER_CONFIG_DISABLED = {
|
|
65
|
+
enabled: false,
|
|
66
|
+
strategy: 'supercluster' as const,
|
|
67
|
+
radius: 80,
|
|
68
|
+
minimumClusterSize: 2,
|
|
69
|
+
maxZoom: 20,
|
|
70
|
+
backgroundColor: Colors.blue,
|
|
71
|
+
textColor: Colors.white,
|
|
72
|
+
borderWidth: 2,
|
|
73
|
+
borderColor: Colors.white,
|
|
74
|
+
animatesClusters: true,
|
|
75
|
+
animateOnReappear: true,
|
|
76
|
+
animationDuration: 0.3,
|
|
77
|
+
realtimeClustering: false,
|
|
78
|
+
renderBuffer: 0,
|
|
79
|
+
throttleInterval: 150,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Extended props with style and children.
|
|
83
|
+
// minZoom, maxZoom, mapPadding are non-optional in the Nitro spec (ADR-009)
|
|
84
|
+
// but optional for consumers — we apply defaults in the component.
|
|
85
|
+
//
|
|
86
|
+
// Generic parameter P narrows the `theme` prop to the correct type for
|
|
87
|
+
// the chosen provider. Defaults to 'google' when provider is omitted.
|
|
88
|
+
export interface NitroMapProps<P extends MapProvider = 'google'>
|
|
89
|
+
extends Omit<
|
|
90
|
+
NitroMapPropsSpec,
|
|
91
|
+
| 'style'
|
|
92
|
+
| 'hybridRef'
|
|
93
|
+
| 'minZoom'
|
|
94
|
+
| 'maxZoom'
|
|
95
|
+
| 'mapPadding'
|
|
96
|
+
| 'customMapStyle'
|
|
97
|
+
| 'provider'
|
|
98
|
+
| 'userLocationImage'
|
|
99
|
+
| 'userLocationSize'
|
|
100
|
+
> {
|
|
51
101
|
style?: StyleProp<ViewStyle>;
|
|
52
102
|
children?: React.ReactNode;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Map provider to use. Typed as generic `P` so that `theme` narrows
|
|
106
|
+
* to the correct provider-specific type.
|
|
107
|
+
* @default 'google'
|
|
108
|
+
*/
|
|
109
|
+
provider?: P;
|
|
110
|
+
/** Minimum zoom level (1 = world). @default 1 */
|
|
111
|
+
minZoom?: number;
|
|
112
|
+
/** Maximum zoom level (22 = building). @default 22 */
|
|
113
|
+
maxZoom?: number;
|
|
114
|
+
/** URL or asset name for custom user location icon. @default '' */
|
|
115
|
+
userLocationImage?: string;
|
|
116
|
+
/** Size of the custom user location icon in points. @default 40 */
|
|
117
|
+
userLocationSize?: number;
|
|
118
|
+
/**
|
|
119
|
+
* Padding around map edges to offset center and controls.
|
|
120
|
+
* Pass a single number for uniform padding on all sides,
|
|
121
|
+
* or an EdgePadding object for per-side control.
|
|
122
|
+
* @default {0,0,0,0}
|
|
123
|
+
*/
|
|
124
|
+
mapPadding?: number | EdgePadding;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Provider-aware map theme. The accepted type depends on the `provider` prop:
|
|
128
|
+
* - `'google'` → `GoogleMapTheme` (JSON style array)
|
|
129
|
+
* - `'apple'` → `AppleMapTheme` (configuration object) — Phase 3
|
|
130
|
+
* - `'yandex'` → `YandexMapTheme` (style URI / night mode) — Phase 4
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```tsx
|
|
134
|
+
* // Google — JSON style array
|
|
135
|
+
* <NitroMap provider="google" theme={[
|
|
136
|
+
* { featureType: 'water', stylers: [{ color: '#0e171d' }] },
|
|
137
|
+
* ]} />
|
|
138
|
+
*
|
|
139
|
+
* // Apple (future) — configuration object
|
|
140
|
+
* <NitroMap provider="apple" theme={{
|
|
141
|
+
* colorScheme: 'dark',
|
|
142
|
+
* emphasisStyle: 'muted',
|
|
143
|
+
* }} />
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
theme?: ThemeForProvider[P];
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @deprecated Use `theme` instead. `customMapStyle` only supports Google Maps
|
|
150
|
+
* JSON format and will be removed in a future version.
|
|
151
|
+
*/
|
|
152
|
+
customMapStyle?: MapStyle;
|
|
53
153
|
}
|
|
54
154
|
|
|
55
155
|
// Ref type
|
|
56
156
|
export type NitroMapRef = NitroMapMethods;
|
|
57
157
|
|
|
58
158
|
/**
|
|
59
|
-
* NitroMap - High-performance
|
|
159
|
+
* NitroMap - High-performance map component with native markers.
|
|
160
|
+
* Supports multiple providers (Google, Apple, Yandex) with type-safe theming.
|
|
60
161
|
*/
|
|
61
162
|
const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
62
163
|
(
|
|
@@ -65,6 +166,7 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
65
166
|
children,
|
|
66
167
|
provider,
|
|
67
168
|
initialRegion,
|
|
169
|
+
region,
|
|
68
170
|
showsUserLocation = false,
|
|
69
171
|
zoomEnabled = true,
|
|
70
172
|
scrollEnabled = true,
|
|
@@ -72,8 +174,13 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
72
174
|
pitchEnabled = true,
|
|
73
175
|
darkMode = false,
|
|
74
176
|
mapType = 'standard',
|
|
75
|
-
showsMyLocationButton = false,
|
|
76
177
|
clusterConfig,
|
|
178
|
+
mapPadding,
|
|
179
|
+
showsTraffic = false,
|
|
180
|
+
showsBuildings = true,
|
|
181
|
+
showsCompass = true,
|
|
182
|
+
minZoom,
|
|
183
|
+
maxZoom,
|
|
77
184
|
onPress,
|
|
78
185
|
onLongPress,
|
|
79
186
|
onMapReady,
|
|
@@ -84,77 +191,96 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
84
191
|
onMarkerDrag,
|
|
85
192
|
onMarkerDragEnd,
|
|
86
193
|
onClusterPress,
|
|
194
|
+
onPolylinePress,
|
|
195
|
+
onPolygonPress,
|
|
196
|
+
onCirclePress,
|
|
197
|
+
onUserLocationChange,
|
|
198
|
+
onUserTrackingModeChange,
|
|
199
|
+
onUserLocationError,
|
|
200
|
+
onMapIdle,
|
|
87
201
|
onError,
|
|
202
|
+
userTrackingMode = 'none',
|
|
203
|
+
userLocationImage = '',
|
|
204
|
+
userLocationSize = 40,
|
|
205
|
+
userLocationAnchor = { x: 0.5, y: 0.5 },
|
|
206
|
+
theme,
|
|
207
|
+
customMapStyle,
|
|
88
208
|
...rest
|
|
89
209
|
},
|
|
90
210
|
ref
|
|
91
211
|
) => {
|
|
212
|
+
// Dev-mode warning for unimplemented providers
|
|
213
|
+
if (__DEV__ && provider && provider !== 'google') {
|
|
214
|
+
console.warn(
|
|
215
|
+
`[NitroMap] Provider "${provider}" is not yet implemented. ` +
|
|
216
|
+
'Falling back to Google Maps. See ROADMAP for provider status.'
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Dev-mode deprecation warning for customMapStyle
|
|
221
|
+
if (__DEV__ && customMapStyle && !theme) {
|
|
222
|
+
console.warn(
|
|
223
|
+
'[NitroMap] `customMapStyle` is deprecated. Use `theme` instead.'
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Resolve theme → native bridge prop.
|
|
228
|
+
// `theme` takes precedence over deprecated `customMapStyle`.
|
|
229
|
+
// Currently only Google is implemented — theme is passed as customMapStyle.
|
|
230
|
+
// When Apple/Yandex are added, this will route to the correct native prop.
|
|
231
|
+
const resolvedMapStyle: MapStyle | undefined = useMemo(() => {
|
|
232
|
+
if (theme) {
|
|
233
|
+
// Google provider: theme is already MapStyleElement[] (GoogleMapTheme)
|
|
234
|
+
// Apple/Yandex: will be handled by their respective native props
|
|
235
|
+
const resolvedProvider = provider ?? 'google';
|
|
236
|
+
if (resolvedProvider === 'google') {
|
|
237
|
+
return theme as MapStyle;
|
|
238
|
+
}
|
|
239
|
+
// Future providers: return undefined here, pass theme via separate native prop
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
return customMapStyle;
|
|
243
|
+
}, [theme, customMapStyle, provider]);
|
|
244
|
+
|
|
92
245
|
// Native ref
|
|
93
246
|
const nativeRef = useRef<NitroMapMethods | null>(null);
|
|
94
247
|
|
|
95
248
|
// Marker handlers registry
|
|
96
249
|
const markerHandlersRef = useRef<Map<string, MarkerHandlers>>(new Map());
|
|
97
250
|
|
|
251
|
+
// Active marker ID tracking for duplicate detection (__DEV__ only)
|
|
252
|
+
const activeMarkerIdsRef = useRef<Set<string>>(new Set());
|
|
253
|
+
|
|
98
254
|
// Track if map is ready
|
|
99
255
|
const [isReady, setIsReady] = useState(false);
|
|
100
256
|
|
|
101
|
-
// Expose
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
nativeRef.current?.addMarker(marker);
|
|
129
|
-
},
|
|
130
|
-
addMarkers: (markers) => {
|
|
131
|
-
nativeRef.current?.addMarkers(markers);
|
|
132
|
-
},
|
|
133
|
-
updateMarker: (marker) => {
|
|
134
|
-
nativeRef.current?.updateMarker(marker);
|
|
135
|
-
},
|
|
136
|
-
removeMarker: (id) => {
|
|
137
|
-
nativeRef.current?.removeMarker(id);
|
|
138
|
-
},
|
|
139
|
-
clearMarkers: () => {
|
|
140
|
-
nativeRef.current?.clearMarkers();
|
|
141
|
-
},
|
|
142
|
-
setClusteringEnabled: (enabled) => {
|
|
143
|
-
nativeRef.current?.setClusteringEnabled(enabled);
|
|
144
|
-
},
|
|
145
|
-
refreshClusters: () => {
|
|
146
|
-
nativeRef.current?.refreshClusters();
|
|
147
|
-
},
|
|
148
|
-
selectMarker: (id: string) => {
|
|
149
|
-
nativeRef.current?.selectMarker(id);
|
|
150
|
-
},
|
|
151
|
-
setMapStyle: (mapStyle: MapStyle) => {
|
|
152
|
-
nativeRef.current?.setMapStyle(mapStyle);
|
|
153
|
-
},
|
|
154
|
-
setIsDarkMode: (enabled: boolean) => {
|
|
155
|
-
nativeRef.current?.setIsDarkMode(enabled);
|
|
156
|
-
},
|
|
157
|
-
}));
|
|
257
|
+
// Expose all NitroMapMethods via ref by forwarding calls to the native ref.
|
|
258
|
+
// Uses a Proxy to avoid maintaining a 1:1 list of ~25 wrapper methods.
|
|
259
|
+
useImperativeHandle(ref, () => {
|
|
260
|
+
const handler: ProxyHandler<NitroMapMethods> = {
|
|
261
|
+
get(_target, prop: string) {
|
|
262
|
+
return (...args: unknown[]) => {
|
|
263
|
+
const native = nativeRef.current;
|
|
264
|
+
if (!native) {
|
|
265
|
+
// Methods that return Promises should reject; void methods silently no-op.
|
|
266
|
+
if (prop === 'getCamera' || prop === 'getMapBoundaries') {
|
|
267
|
+
return Promise.reject(new Error('Map not ready'));
|
|
268
|
+
}
|
|
269
|
+
if (
|
|
270
|
+
prop === 'pointForCoordinate' ||
|
|
271
|
+
prop === 'coordinateForPoint'
|
|
272
|
+
) {
|
|
273
|
+
throw new Error('Map not ready');
|
|
274
|
+
}
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return (native as any)[prop]?.(...args);
|
|
279
|
+
};
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
return new Proxy({} as NitroMapMethods, handler);
|
|
283
|
+
});
|
|
158
284
|
|
|
159
285
|
// Handle hybridRef callback
|
|
160
286
|
|
|
@@ -164,9 +290,16 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
164
290
|
onMapReady?.();
|
|
165
291
|
}, [onMapReady]);
|
|
166
292
|
|
|
293
|
+
// Cleanup marker handlers on unmount to prevent memory leaks
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
const handlers = markerHandlersRef.current;
|
|
296
|
+
return () => {
|
|
297
|
+
handlers.clear();
|
|
298
|
+
};
|
|
299
|
+
}, []);
|
|
300
|
+
|
|
167
301
|
// Safety guard: warn if NitroMapInitialize() was not called before rendering
|
|
168
302
|
useEffect(() => {
|
|
169
|
-
const { IsNitroMapInitialized } = require('../modules');
|
|
170
303
|
if (!IsNitroMapInitialized()) {
|
|
171
304
|
onError?.({
|
|
172
305
|
code: 'NOT_INITIALIZED',
|
|
@@ -175,6 +308,7 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
175
308
|
'Call it in your app entry point or a useEffect before the map mounts.',
|
|
176
309
|
});
|
|
177
310
|
}
|
|
311
|
+
// onError is excluded — we only check initialization once on mount.
|
|
178
312
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
179
313
|
}, []);
|
|
180
314
|
|
|
@@ -226,7 +360,9 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
226
360
|
[onClusterPress]
|
|
227
361
|
);
|
|
228
362
|
|
|
229
|
-
// Context value
|
|
363
|
+
// Context value — uses useRef to create a stable reference that won't
|
|
364
|
+
// trigger re-renders on children. mapRef is mutated in the hybridRef
|
|
365
|
+
// callback, but consumers access it lazily (in effects, not during render).
|
|
230
366
|
const contextValue = useRef({
|
|
231
367
|
mapRef: null as NitroMapMethods | null,
|
|
232
368
|
|
|
@@ -241,6 +377,20 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
241
377
|
getMarkerHandler: (id: string) => {
|
|
242
378
|
return markerHandlersRef.current.get(id);
|
|
243
379
|
},
|
|
380
|
+
|
|
381
|
+
trackMarkerId: (id: string) => {
|
|
382
|
+
if (__DEV__ && activeMarkerIdsRef.current.has(id)) {
|
|
383
|
+
console.warn(
|
|
384
|
+
`[NitroMap] Duplicate marker ID "${id}" detected. ` +
|
|
385
|
+
'Each marker must have a unique ID. The previous marker with this ID will be replaced.'
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
activeMarkerIdsRef.current.add(id);
|
|
389
|
+
},
|
|
390
|
+
|
|
391
|
+
untrackMarkerId: (id: string) => {
|
|
392
|
+
activeMarkerIdsRef.current.delete(id);
|
|
393
|
+
},
|
|
244
394
|
}).current;
|
|
245
395
|
|
|
246
396
|
// Memoize style to prevent new array on every render
|
|
@@ -268,8 +418,8 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
268
418
|
borderColor:
|
|
269
419
|
parseColor(clusterConfig.borderColor) ?? defaultBorderColor,
|
|
270
420
|
animatesClusters: clusterConfig.animatesClusters ?? true,
|
|
421
|
+
animateOnReappear: clusterConfig.animateOnReappear ?? true,
|
|
271
422
|
animationDuration: clusterConfig.animationDuration ?? 0.3,
|
|
272
|
-
animationStyle: clusterConfig.animationStyle ?? 'default',
|
|
273
423
|
realtimeClustering: clusterConfig.realtimeClustering ?? false,
|
|
274
424
|
renderBuffer: clusterConfig.renderBuffer ?? 0,
|
|
275
425
|
throttleInterval: clusterConfig.throttleInterval ?? 150,
|
|
@@ -299,6 +449,13 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
299
449
|
onMarkerDrag: callback(handleMarkerDrag),
|
|
300
450
|
onMarkerDragEnd: callback(handleMarkerDragEnd),
|
|
301
451
|
onClusterPress: callback(handleClusterPress),
|
|
452
|
+
onPolylinePress: callback(onPolylinePress),
|
|
453
|
+
onPolygonPress: callback(onPolygonPress),
|
|
454
|
+
onCirclePress: callback(onCirclePress),
|
|
455
|
+
onUserLocationChange: callback(onUserLocationChange),
|
|
456
|
+
onUserTrackingModeChange: callback(onUserTrackingModeChange),
|
|
457
|
+
onUserLocationError: callback(onUserLocationError),
|
|
458
|
+
onMapIdle: callback(onMapIdle),
|
|
302
459
|
onError: callback(onError),
|
|
303
460
|
}),
|
|
304
461
|
[
|
|
@@ -312,6 +469,13 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
312
469
|
handleMarkerDrag,
|
|
313
470
|
handleMarkerDragEnd,
|
|
314
471
|
handleClusterPress,
|
|
472
|
+
onPolylinePress,
|
|
473
|
+
onPolygonPress,
|
|
474
|
+
onCirclePress,
|
|
475
|
+
onUserLocationChange,
|
|
476
|
+
onUserTrackingModeChange,
|
|
477
|
+
onUserLocationError,
|
|
478
|
+
onMapIdle,
|
|
315
479
|
onError,
|
|
316
480
|
]
|
|
317
481
|
);
|
|
@@ -321,8 +485,9 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
321
485
|
<NitroMapHostComponent
|
|
322
486
|
style={combinedStyle}
|
|
323
487
|
hybridRef={hybridRefCallback}
|
|
324
|
-
provider={provider ??
|
|
325
|
-
initialRegion={initialRegion}
|
|
488
|
+
provider={provider ?? 'google'}
|
|
489
|
+
initialRegion={initialRegion ?? REGION_UNSET}
|
|
490
|
+
region={region ?? REGION_UNSET}
|
|
326
491
|
showsUserLocation={showsUserLocation}
|
|
327
492
|
zoomEnabled={zoomEnabled}
|
|
328
493
|
scrollEnabled={scrollEnabled}
|
|
@@ -330,8 +495,27 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
330
495
|
pitchEnabled={pitchEnabled}
|
|
331
496
|
mapType={mapType}
|
|
332
497
|
darkMode={darkMode}
|
|
333
|
-
|
|
334
|
-
|
|
498
|
+
clusterConfig={parsedClusterConfig ?? CLUSTER_CONFIG_DISABLED}
|
|
499
|
+
mapPadding={
|
|
500
|
+
typeof mapPadding === 'number'
|
|
501
|
+
? {
|
|
502
|
+
top: mapPadding,
|
|
503
|
+
right: mapPadding,
|
|
504
|
+
bottom: mapPadding,
|
|
505
|
+
left: mapPadding,
|
|
506
|
+
}
|
|
507
|
+
: mapPadding ?? { top: 0, right: 0, bottom: 0, left: 0 }
|
|
508
|
+
}
|
|
509
|
+
showsCompass={showsCompass}
|
|
510
|
+
showsTraffic={showsTraffic}
|
|
511
|
+
showsBuildings={showsBuildings}
|
|
512
|
+
minZoom={minZoom ?? 1}
|
|
513
|
+
maxZoom={maxZoom ?? 22}
|
|
514
|
+
userTrackingMode={userTrackingMode}
|
|
515
|
+
userLocationImage={userLocationImage}
|
|
516
|
+
userLocationSize={userLocationSize}
|
|
517
|
+
userLocationAnchor={userLocationAnchor}
|
|
518
|
+
customMapStyle={resolvedMapStyle ?? []}
|
|
335
519
|
onPress={memoizedCallbacks.onPress}
|
|
336
520
|
onLongPress={memoizedCallbacks.onLongPress}
|
|
337
521
|
onMapReady={memoizedCallbacks.onMapReady}
|
|
@@ -342,6 +526,13 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
342
526
|
onMarkerDrag={memoizedCallbacks.onMarkerDrag}
|
|
343
527
|
onMarkerDragEnd={memoizedCallbacks.onMarkerDragEnd}
|
|
344
528
|
onClusterPress={memoizedCallbacks.onClusterPress}
|
|
529
|
+
onPolylinePress={memoizedCallbacks.onPolylinePress}
|
|
530
|
+
onPolygonPress={memoizedCallbacks.onPolygonPress}
|
|
531
|
+
onCirclePress={memoizedCallbacks.onCirclePress}
|
|
532
|
+
onUserLocationChange={memoizedCallbacks.onUserLocationChange}
|
|
533
|
+
onUserTrackingModeChange={memoizedCallbacks.onUserTrackingModeChange}
|
|
534
|
+
onUserLocationError={memoizedCallbacks.onUserLocationError}
|
|
535
|
+
onMapIdle={memoizedCallbacks.onMapIdle}
|
|
345
536
|
onError={memoizedCallbacks.onError}
|
|
346
537
|
{...rest}
|
|
347
538
|
/>
|
|
@@ -352,7 +543,7 @@ const NitroMapInner = forwardRef<NitroMapRef, NitroMapProps>(
|
|
|
352
543
|
}
|
|
353
544
|
);
|
|
354
545
|
|
|
355
|
-
NitroMapInner.displayName = '
|
|
546
|
+
NitroMapInner.displayName = 'NitroMapInner';
|
|
356
547
|
|
|
357
548
|
// ============ Custom Props Comparison ============
|
|
358
549
|
// Deep compare map props to prevent unnecessary re-renders
|
|
@@ -364,17 +555,49 @@ const areMapPropsEqual = (
|
|
|
364
555
|
if (
|
|
365
556
|
prevProps.provider !== nextProps.provider ||
|
|
366
557
|
prevProps.showsUserLocation !== nextProps.showsUserLocation ||
|
|
558
|
+
prevProps.userTrackingMode !== nextProps.userTrackingMode ||
|
|
559
|
+
prevProps.userLocationImage !== nextProps.userLocationImage ||
|
|
560
|
+
prevProps.userLocationSize !== nextProps.userLocationSize ||
|
|
561
|
+
prevProps.userLocationAnchor?.x !== nextProps.userLocationAnchor?.x ||
|
|
562
|
+
prevProps.userLocationAnchor?.y !== nextProps.userLocationAnchor?.y ||
|
|
367
563
|
prevProps.zoomEnabled !== nextProps.zoomEnabled ||
|
|
368
564
|
prevProps.scrollEnabled !== nextProps.scrollEnabled ||
|
|
369
565
|
prevProps.rotateEnabled !== nextProps.rotateEnabled ||
|
|
370
566
|
prevProps.pitchEnabled !== nextProps.pitchEnabled ||
|
|
371
567
|
prevProps.darkMode !== nextProps.darkMode ||
|
|
372
568
|
prevProps.mapType !== nextProps.mapType ||
|
|
373
|
-
prevProps.
|
|
569
|
+
prevProps.showsTraffic !== nextProps.showsTraffic ||
|
|
570
|
+
prevProps.showsBuildings !== nextProps.showsBuildings ||
|
|
571
|
+
prevProps.showsCompass !== nextProps.showsCompass ||
|
|
572
|
+
prevProps.minZoom !== nextProps.minZoom ||
|
|
573
|
+
prevProps.maxZoom !== nextProps.maxZoom ||
|
|
574
|
+
prevProps.theme !== nextProps.theme ||
|
|
575
|
+
prevProps.customMapStyle !== nextProps.customMapStyle
|
|
374
576
|
) {
|
|
375
577
|
return false;
|
|
376
578
|
}
|
|
377
579
|
|
|
580
|
+
// Compare mapPadding (handles number | EdgePadding union)
|
|
581
|
+
const prevPadding = prevProps.mapPadding;
|
|
582
|
+
const nextPadding = nextProps.mapPadding;
|
|
583
|
+
if (typeof prevPadding !== typeof nextPadding) {
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
if (typeof prevPadding === 'number') {
|
|
587
|
+
if (prevPadding !== nextPadding) return false;
|
|
588
|
+
} else if (prevPadding && nextPadding && typeof nextPadding === 'object') {
|
|
589
|
+
if (
|
|
590
|
+
prevPadding.top !== nextPadding.top ||
|
|
591
|
+
prevPadding.right !== nextPadding.right ||
|
|
592
|
+
prevPadding.bottom !== nextPadding.bottom ||
|
|
593
|
+
prevPadding.left !== nextPadding.left
|
|
594
|
+
) {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
} else if (prevPadding !== nextPadding) {
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
|
|
378
601
|
// Compare initialRegion (deep)
|
|
379
602
|
const prevRegion = prevProps.initialRegion;
|
|
380
603
|
const nextRegion = nextProps.initialRegion;
|
|
@@ -402,11 +625,18 @@ const areMapPropsEqual = (
|
|
|
402
625
|
prevCluster.minimumClusterSize !== nextCluster.minimumClusterSize ||
|
|
403
626
|
prevCluster.maxZoom !== nextCluster.maxZoom ||
|
|
404
627
|
prevCluster.animatesClusters !== nextCluster.animatesClusters ||
|
|
628
|
+
prevCluster.animateOnReappear !== nextCluster.animateOnReappear ||
|
|
405
629
|
prevCluster.animationDuration !== nextCluster.animationDuration ||
|
|
406
|
-
prevCluster.
|
|
630
|
+
prevCluster.borderWidth !== nextCluster.borderWidth ||
|
|
407
631
|
prevCluster.realtimeClustering !== nextCluster.realtimeClustering ||
|
|
408
632
|
prevCluster.renderBuffer !== nextCluster.renderBuffer ||
|
|
409
|
-
prevCluster.throttleInterval !== nextCluster.throttleInterval
|
|
633
|
+
prevCluster.throttleInterval !== nextCluster.throttleInterval ||
|
|
634
|
+
!areColorsEqual(
|
|
635
|
+
prevCluster.backgroundColor,
|
|
636
|
+
nextCluster.backgroundColor
|
|
637
|
+
) ||
|
|
638
|
+
!areColorsEqual(prevCluster.textColor, nextCluster.textColor) ||
|
|
639
|
+
!areColorsEqual(prevCluster.borderColor, nextCluster.borderColor)
|
|
410
640
|
) {
|
|
411
641
|
return false;
|
|
412
642
|
}
|
|
@@ -432,8 +662,28 @@ const areMapPropsEqual = (
|
|
|
432
662
|
return true;
|
|
433
663
|
};
|
|
434
664
|
|
|
665
|
+
// ============ Generic Component Type ============
|
|
666
|
+
// React's forwardRef + memo erase generics, so we define a generic
|
|
667
|
+
// function signature and cast the memoized component to it.
|
|
668
|
+
// This lets consumers write <NitroMap provider="apple" theme={...} />
|
|
669
|
+
// and get proper type narrowing on the `theme` prop.
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Generic NitroMap component type that preserves provider-aware theme typing.
|
|
673
|
+
*/
|
|
674
|
+
interface NitroMapComponent {
|
|
675
|
+
<P extends MapProvider = 'google'>(
|
|
676
|
+
props: NitroMapProps<P> & React.RefAttributes<NitroMapRef>
|
|
677
|
+
): React.ReactElement | null;
|
|
678
|
+
displayName?: string;
|
|
679
|
+
}
|
|
680
|
+
|
|
435
681
|
// Memoized NitroMap to prevent unnecessary re-renders
|
|
436
|
-
const
|
|
682
|
+
const NitroMapMemoized = memo(NitroMapInner, areMapPropsEqual);
|
|
683
|
+
|
|
684
|
+
// Cast to generic component type so consumers get provider-aware theme narrowing
|
|
685
|
+
const NitroMap = NitroMapMemoized as unknown as NitroMapComponent;
|
|
686
|
+
NitroMap.displayName = 'NitroMap';
|
|
437
687
|
|
|
438
688
|
const styles = StyleSheet.create({
|
|
439
689
|
default: {
|
|
@@ -441,5 +691,5 @@ const styles = StyleSheet.create({
|
|
|
441
691
|
},
|
|
442
692
|
});
|
|
443
693
|
|
|
444
|
-
export { NitroMap };
|
|
694
|
+
export { NitroMap, areMapPropsEqual };
|
|
445
695
|
export default NitroMap;
|