react-native-leaflet-kit 1.0.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 +21 -0
- package/README.md +410 -0
- package/dist/components/Circle.d.ts +4 -0
- package/dist/components/Circle.d.ts.map +1 -0
- package/dist/components/Circle.js +15 -0
- package/dist/components/Circle.js.map +1 -0
- package/dist/components/GeoJSON.d.ts +4 -0
- package/dist/components/GeoJSON.d.ts.map +1 -0
- package/dist/components/GeoJSON.js +14 -0
- package/dist/components/GeoJSON.js.map +1 -0
- package/dist/components/Heatmap.d.ts +4 -0
- package/dist/components/Heatmap.d.ts.map +1 -0
- package/dist/components/Heatmap.js +14 -0
- package/dist/components/Heatmap.js.map +1 -0
- package/dist/components/MapContainer.d.ts +9 -0
- package/dist/components/MapContainer.d.ts.map +1 -0
- package/dist/components/MapContainer.js +86 -0
- package/dist/components/MapContainer.js.map +1 -0
- package/dist/components/Marker.d.ts +7 -0
- package/dist/components/Marker.d.ts.map +1 -0
- package/dist/components/Marker.js +20 -0
- package/dist/components/Marker.js.map +1 -0
- package/dist/components/MarkerCluster.d.ts +4 -0
- package/dist/components/MarkerCluster.d.ts.map +1 -0
- package/dist/components/MarkerCluster.js +14 -0
- package/dist/components/MarkerCluster.js.map +1 -0
- package/dist/components/Polygon.d.ts +4 -0
- package/dist/components/Polygon.d.ts.map +1 -0
- package/dist/components/Polygon.js +15 -0
- package/dist/components/Polygon.js.map +1 -0
- package/dist/components/Polyline.d.ts +4 -0
- package/dist/components/Polyline.d.ts.map +1 -0
- package/dist/components/Polyline.js +14 -0
- package/dist/components/Polyline.js.map +1 -0
- package/dist/components/Popup.d.ts +4 -0
- package/dist/components/Popup.d.ts.map +1 -0
- package/dist/components/Popup.js +27 -0
- package/dist/components/Popup.js.map +1 -0
- package/dist/components/TileLayer.d.ts +4 -0
- package/dist/components/TileLayer.d.ts.map +1 -0
- package/dist/components/TileLayer.js +14 -0
- package/dist/components/TileLayer.js.map +1 -0
- package/dist/components/UserMarker.d.ts +4 -0
- package/dist/components/UserMarker.d.ts.map +1 -0
- package/dist/components/UserMarker.js +15 -0
- package/dist/components/UserMarker.js.map +1 -0
- package/dist/context/MapContext.d.ts +11 -0
- package/dist/context/MapContext.d.ts.map +1 -0
- package/dist/context/MapContext.js +11 -0
- package/dist/context/MapContext.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/LeafletHTML.d.ts +2 -0
- package/dist/templates/LeafletHTML.d.ts.map +1 -0
- package/dist/templates/LeafletHTML.js +539 -0
- package/dist/templates/LeafletHTML.js.map +1 -0
- package/dist/types/index.d.ts +155 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +15 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/deepEqual.d.ts +2 -0
- package/dist/utils/deepEqual.d.ts.map +1 -0
- package/dist/utils/deepEqual.js +22 -0
- package/dist/utils/deepEqual.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 React Native Leaflet Kit Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# React Native Leaflet Kit 🗺️
|
|
2
|
+
|
|
3
|
+
A professional, pluggable, and declarative Map library for React Native built on top of Leaflet, WebView, and OpenStreetMap tiles. Designed with a Compound Component pattern for maximum flexibility and performance.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- **Declarative API**: Build maps using clean, modular JSX components.
|
|
8
|
+
- **Compound Component Pattern**: Easily compose layers, markers, and polylines.
|
|
9
|
+
- **Surgical Updates**: Only modified elements are updated, preventing full map re-renders.
|
|
10
|
+
- **Premium User Location**: Integrated high-performance user marker with direction cone and pulse animation.
|
|
11
|
+
- **TypeScript Support**: Fully typed for a superior developer experience.
|
|
12
|
+
- **Theming**: Seamless support for Light and Dark modes.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 🚀 Installation
|
|
17
|
+
|
|
18
|
+
Install the library and its peer dependency:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install react-native-leaflet-kit react-native-webview
|
|
22
|
+
# or
|
|
23
|
+
yarn add react-native-leaflet-kit react-native-webview
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🛠️ Quick Start
|
|
29
|
+
|
|
30
|
+
Wrap your map elements inside the `MapContainer` and add layers as needed.
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { MapContainer, TileLayer, Marker, Polyline } from '@/components/map-library';
|
|
34
|
+
|
|
35
|
+
const MyMap = () => {
|
|
36
|
+
return (
|
|
37
|
+
<MapContainer
|
|
38
|
+
center={{ lat: 28.7041, lng: 77.1025 }}
|
|
39
|
+
zoom={13}
|
|
40
|
+
isDark={true}
|
|
41
|
+
fitBounds={true}
|
|
42
|
+
>
|
|
43
|
+
<TileLayer />
|
|
44
|
+
|
|
45
|
+
<Marker
|
|
46
|
+
id="station-1"
|
|
47
|
+
position={{ lat: 28.7041, lng: 77.1025 }}
|
|
48
|
+
title="Delhi Station"
|
|
49
|
+
/>
|
|
50
|
+
</MapContainer>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 🏎️ Using the Metride Wrapper
|
|
56
|
+
For the most streamlined experience, use the `MetrideMap` component which handles all boilerplate:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { MetrideMap } from '@/components/metro/MetrideMap';
|
|
60
|
+
|
|
61
|
+
<MetrideMap
|
|
62
|
+
markers={myStations}
|
|
63
|
+
paths={myRouteLines}
|
|
64
|
+
userMarker={currentUserLocation}
|
|
65
|
+
fitBounds={true}
|
|
66
|
+
isDark={true}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🧩 Component Documentation
|
|
75
|
+
|
|
76
|
+
### 1. `<MapContainer />`
|
|
77
|
+
The primary wrapper that initializes the WebView and provides the Map Context.
|
|
78
|
+
|
|
79
|
+
| Prop | Type | Default | Description |
|
|
80
|
+
| :--- | :--- | :--- | :--- |
|
|
81
|
+
| `center` | `LatLng` | - | Initial center coordinates `{ lat, lng }`. |
|
|
82
|
+
| `zoom` | `number` | `13` | Initial zoom level. |
|
|
83
|
+
| `isDark` | `boolean` | `false` | Toggles dark mode tiles filter. |
|
|
84
|
+
| `backgroundColor` | `string` | `#ffffff` | WebView background color. |
|
|
85
|
+
| `fitBounds` | `boolean` | `false` | Enables automatic framing of the map content. |
|
|
86
|
+
| `onMapReady` | `() => void` | - | Called when the map is fully loaded. |
|
|
87
|
+
| `onUserGesture`| `() => void` | - | Called when the user manually pans or zooms (disables fitBounds). |
|
|
88
|
+
| `onMapClick` | `(pos: LatLng) => void` | - | Called when the map is tapped. |
|
|
89
|
+
|
|
90
|
+
**Example:**
|
|
91
|
+
```tsx
|
|
92
|
+
<MapContainer
|
|
93
|
+
ref={mapRef}
|
|
94
|
+
center={{ lat: 28.6139, lng: 77.2090 }}
|
|
95
|
+
onMapClick={(pos) => console.log('Tapped at:', pos)}
|
|
96
|
+
>
|
|
97
|
+
{/* Children go here */}
|
|
98
|
+
</MapContainer>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### 2. `<TileLayer />`
|
|
104
|
+
Defines the source of the map tiles.
|
|
105
|
+
|
|
106
|
+
| Prop | Type | Default | Description |
|
|
107
|
+
| :--- | :--- | :--- | :--- |
|
|
108
|
+
| `url` | `string` | `OSM Standard` | Standard Tile URL pattern. Defaults to OpenStreetMap. |
|
|
109
|
+
| `attribution` | `string` | - | Small text displayed at footer for credits. |
|
|
110
|
+
|
|
111
|
+
**Example (Default):**
|
|
112
|
+
```tsx
|
|
113
|
+
<TileLayer />
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Example (Custom Source):**
|
|
117
|
+
```tsx
|
|
118
|
+
<TileLayer
|
|
119
|
+
url="https://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png"
|
|
120
|
+
attribution='© Thunderforest'
|
|
121
|
+
/>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### 3. `<Marker />`
|
|
127
|
+
Adds a standard or custom icon marker to the map.
|
|
128
|
+
|
|
129
|
+
| Prop | Type | Default | Description |
|
|
130
|
+
| :--- | :--- | :--- | :--- |
|
|
131
|
+
| `id` | `string` | - | Unique identifier for the marker. |
|
|
132
|
+
| `position` | `LatLng` | - | Coordinates for placement. |
|
|
133
|
+
| `title` | `string` | - | Text shown in a popup when tapped. |
|
|
134
|
+
| `icon` | `string` | - | Can be an Emoji, remote URL, or HTML string. |
|
|
135
|
+
| `size` | `[number, number]` | `[32, 32]` | Icon dimensions. |
|
|
136
|
+
|
|
137
|
+
**Example:**
|
|
138
|
+
```tsx
|
|
139
|
+
<Marker
|
|
140
|
+
id="main-pin"
|
|
141
|
+
position={{ lat: 28.6139, lng: 77.2090 }}
|
|
142
|
+
icon="⭐"
|
|
143
|
+
title="New Delhi Capital"
|
|
144
|
+
size={[40, 40]}
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### 4. `<Polyline />`
|
|
151
|
+
Draws paths or routes on the map.
|
|
152
|
+
|
|
153
|
+
| Prop | Type | Default | Description |
|
|
154
|
+
| :--- | :--- | :--- | :--- |
|
|
155
|
+
| `id` | `string` | - | Unique identifier. |
|
|
156
|
+
| `positions` | `LatLng[]` | - | Array of coordinates defining the path. |
|
|
157
|
+
| `color` | `string` | `#3388ff` | Hex or RGBA color. |
|
|
158
|
+
| `weight` | `number` | `3` | Thickness of the line. |
|
|
159
|
+
| `opacity` | `number` | `1.0` | Transparency (0 to 1). |
|
|
160
|
+
| `dashArray` | `string` | - | CSS dash pattern (e.g. "5, 10"). |
|
|
161
|
+
| `isAnimated` | `boolean` | `false` | Enable a flowing route animation. |
|
|
162
|
+
|
|
163
|
+
**Regular Example:**
|
|
164
|
+
```tsx
|
|
165
|
+
<Polyline
|
|
166
|
+
id="route-1"
|
|
167
|
+
positions={pathCoordinates}
|
|
168
|
+
color="#e74c3c"
|
|
169
|
+
weight={5}
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Animated (Flowing) Example:**
|
|
174
|
+
```tsx
|
|
175
|
+
<Polyline
|
|
176
|
+
id="moving-route"
|
|
177
|
+
positions={pathCoordinates}
|
|
178
|
+
color="#2ecc71"
|
|
179
|
+
isAnimated={true}
|
|
180
|
+
/>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### 5. `<UserMarker />`
|
|
186
|
+
A specialized premium component for real-time user positioning.
|
|
187
|
+
|
|
188
|
+
| Prop | Type | Description |
|
|
189
|
+
| :--- | :--- | :--- |
|
|
190
|
+
| `position` | `LatLng` | Real-time coordinates. |
|
|
191
|
+
| `heading` | `number` | Heading in degrees (0 = North). |
|
|
192
|
+
| `accuracy` | `number` | Circular accuracy radius in meters. |
|
|
193
|
+
| `markerColor`| `string` | The primary theme color for the pulse and cone. |
|
|
194
|
+
| `style` | `UserLocationStyle` | Deep customization (see below). |
|
|
195
|
+
|
|
196
|
+
**Example:**
|
|
197
|
+
```tsx
|
|
198
|
+
<UserMarker
|
|
199
|
+
position={userPos}
|
|
200
|
+
heading={90}
|
|
201
|
+
accuracy={25}
|
|
202
|
+
markerColor="#2ecc71"
|
|
203
|
+
style={{
|
|
204
|
+
markerSize: 15,
|
|
205
|
+
showPulse: true,
|
|
206
|
+
pulseMaxScale: 3,
|
|
207
|
+
showDirectionCone: true,
|
|
208
|
+
coneOpacity: 0.4
|
|
209
|
+
}}
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### 6. `<Popup />`
|
|
216
|
+
Enables rich HTML content and professional styling inside a `Marker`. Must be a child of `<Marker />`.
|
|
217
|
+
|
|
218
|
+
| Prop | Type | Default | Description |
|
|
219
|
+
| :--- | :--- | :--- | :--- |
|
|
220
|
+
| `content` | `string` | - | (Optional) HTML string content. |
|
|
221
|
+
| `style` | `PopupStyle`| - | Nested object for visual styling (see below). |
|
|
222
|
+
| `autoPan` | `boolean` | `true` | Whether the map should pan to fit the popup. |
|
|
223
|
+
| `offset` | `[number, number]` | `[0, 7]` | Tip-to-anchor offset. |
|
|
224
|
+
|
|
225
|
+
#### `PopupStyle` Properties
|
|
226
|
+
| Property | Type | Description |
|
|
227
|
+
| :--- | :--- | :--- |
|
|
228
|
+
| `backgroundColor` | `string` | Popup background color. |
|
|
229
|
+
| `textColor` | `string` | Text color. |
|
|
230
|
+
| `borderRadius` | `number` | Corner roundness in pixels. |
|
|
231
|
+
| `padding` | `number` | Inner spacing in pixels. |
|
|
232
|
+
| `fontSize` | `number` | Text size in pixels. |
|
|
233
|
+
| `fontWeight` | `string/number`| Text weight. |
|
|
234
|
+
| `maxWidth` | `number` | Maximum width of the popup. |
|
|
235
|
+
| `closeButtonColor`| `string` | Color of the close 'X' button. |
|
|
236
|
+
|
|
237
|
+
**Example:**
|
|
238
|
+
```tsx
|
|
239
|
+
<Marker id="premium-shop" position={pos}>
|
|
240
|
+
<Popup
|
|
241
|
+
style={{
|
|
242
|
+
backgroundColor: "#2c3e50",
|
|
243
|
+
textColor: "#ecf0f1",
|
|
244
|
+
borderRadius: 8,
|
|
245
|
+
padding: 12,
|
|
246
|
+
fontSize: 14
|
|
247
|
+
}}
|
|
248
|
+
offset={[0, 10]}
|
|
249
|
+
>
|
|
250
|
+
<b>Metride Premium Hub</b><br/>
|
|
251
|
+
Authorized Reseller
|
|
252
|
+
</Popup>
|
|
253
|
+
</Marker>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
### 7. `<Circle />`
|
|
259
|
+
Highlights a circular radius on the map.
|
|
260
|
+
|
|
261
|
+
| Prop | Type | Description |
|
|
262
|
+
| :--- | :--- | :--- |
|
|
263
|
+
| `id` | `string` | Unique ID. |
|
|
264
|
+
| `center` | `LatLng` | Center of the circle. |
|
|
265
|
+
| `radius` | `number` | Radius in meters. |
|
|
266
|
+
| `color` | `string` | Border color. |
|
|
267
|
+
| `fillColor` | `string` | Fill color. |
|
|
268
|
+
|
|
269
|
+
**Example:**
|
|
270
|
+
```tsx
|
|
271
|
+
<Circle
|
|
272
|
+
id="danger-zone"
|
|
273
|
+
center={{ lat: 28.7041, lng: 77.1025 }}
|
|
274
|
+
radius={500}
|
|
275
|
+
color="red"
|
|
276
|
+
fillColor="rgba(255, 0, 0, 0.2)"
|
|
277
|
+
/>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
### 8. `<Polygon />`
|
|
283
|
+
Defines a specific area or boundary.
|
|
284
|
+
|
|
285
|
+
| Prop | Type | Description |
|
|
286
|
+
| :--- | :--- | :--- |
|
|
287
|
+
| `id` | `string` | Unique ID. |
|
|
288
|
+
| `positions` | `LatLng[]` | Array of coordinates defining the area. |
|
|
289
|
+
| `color` | `string` | Border color. |
|
|
290
|
+
| `fillColor` | `string` | Fill color. |
|
|
291
|
+
|
|
292
|
+
**Example:**
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### 9. `<GeoJSON />`
|
|
298
|
+
The standard for complex spatial data. Renders entire datasets (lines, points, polygons) from a single JSON.
|
|
299
|
+
|
|
300
|
+
| Prop | Type | Description |
|
|
301
|
+
| :--- | :--- | :--- |
|
|
302
|
+
| `id` | `string` | Unique ID. |
|
|
303
|
+
| `data` | `object` | The GeoJSON object/file content. |
|
|
304
|
+
| `style` | `object` | Styling function or object for the features. |
|
|
305
|
+
|
|
306
|
+
**Example:**
|
|
307
|
+
```tsx
|
|
308
|
+
<GeoJSON
|
|
309
|
+
id="metro-network"
|
|
310
|
+
data={delhiMetroGeoJSON}
|
|
311
|
+
style={{ color: '#ff7800', weight: 5, opacity: 0.65 }}
|
|
312
|
+
/>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### 10. `<MarkerCluster />`
|
|
318
|
+
Optimizes performance and readability by grouping nearby markers.
|
|
319
|
+
|
|
320
|
+
| Prop | Type | Description |
|
|
321
|
+
| :--- | :--- | :--- |
|
|
322
|
+
| `options` | `object` | Leaflet.markercluster configuration. |
|
|
323
|
+
| `children` | `ReactNode` | The markers to be clustered. |
|
|
324
|
+
|
|
325
|
+
**Example:**
|
|
326
|
+
```tsx
|
|
327
|
+
<MarkerCluster options={{ maxClusterRadius: 80 }}>
|
|
328
|
+
{stations.map(s => <Marker key={s.id} {...s} />)}
|
|
329
|
+
</MarkerCluster>
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### 11. `<Heatmap />`
|
|
335
|
+
Visualizes data density (e.g., peak hour congestion).
|
|
336
|
+
|
|
337
|
+
| Prop | Type | Description |
|
|
338
|
+
| :--- | :--- | :--- |
|
|
339
|
+
| `id` | `string` | Unique ID. |
|
|
340
|
+
| `points` | `LatlngIntensity[]` | Array of `{ lat, lng, intensity }`. |
|
|
341
|
+
| `radius` | `number` | Size of the heat points. |
|
|
342
|
+
| `blur` | `number` | Softness of the heat edges. |
|
|
343
|
+
|
|
344
|
+
**Example:**
|
|
345
|
+
```tsx
|
|
346
|
+
<Heatmap
|
|
347
|
+
id="congestion-map"
|
|
348
|
+
points={trafficData}
|
|
349
|
+
radius={30}
|
|
350
|
+
blur={15}
|
|
351
|
+
/>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 🎨 Professional Customization (UserLocationStyle)
|
|
357
|
+
|
|
358
|
+
| Property | Default | Description |
|
|
359
|
+
| :--- | :--- | :--- |
|
|
360
|
+
| `markerSize` | `12` | Inner dot size in pixels. |
|
|
361
|
+
| `showPulse` | `true` | Toggles the radiating pulse animation. |
|
|
362
|
+
| `pulseDuration` | `2.5s` | Speed of the pulse animation. |
|
|
363
|
+
| `pulseMaxScale` | `2.5` | How large the pulse expands. |
|
|
364
|
+
| `showDirectionCone`| `true` | Toggles the field-of-view cone. |
|
|
365
|
+
| `coneWidth` | `60` | Width of the direction cone. |
|
|
366
|
+
| `coneHeight` | `50` | Length of the direction cone. |
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## 🎥 Camera & Interaction Model
|
|
371
|
+
|
|
372
|
+
Our map utilizes a professional state-driven camera system designed to balance automation with user control.
|
|
373
|
+
|
|
374
|
+
### 1. The Priority Priority Engine
|
|
375
|
+
When `fitBounds` is active, the map follows a context-aware hierarchy during initial load:
|
|
376
|
+
- **Priority 1: The Route (Hero)** - If markers or paths exist, the map frames them perfectly while excluding the user (if distant) to keep the journey as the main focus.
|
|
377
|
+
- **Priority 2: The User (Fallback)** - If the map is empty, it centers on the user at a comfortable street-level zoom (Level 15).
|
|
378
|
+
|
|
379
|
+
### 2. Gesture-Aware Automation
|
|
380
|
+
- **Auto-Pause**: If a user performs a manual gesture (pan, zoom, pinch), the map **immediately disables** automatic camera movements to prevent "fighting" the user.
|
|
381
|
+
- **Recenter Pattern**: Developers can use the `onUserGesture` callback to show a "Recenter" button. When clicked, setting `fitBounds={true}` will snap the camera back to the optimal view.
|
|
382
|
+
|
|
383
|
+
### 3. Debounced Handshake
|
|
384
|
+
To prevent "jitter" during data loading, the camera wait **200ms** after the first piece of data arrives before performing the initial fit. This ensures that all markers and polylines have registered through the bridge for a perfect single-frame fit.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## 📜 License
|
|
389
|
+
|
|
390
|
+
MIT License
|
|
391
|
+
|
|
392
|
+
Copyright (c) 2026 Ashish Pradhan
|
|
393
|
+
|
|
394
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
395
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
396
|
+
in the Software without restriction, including without limitation the rights
|
|
397
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
398
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
399
|
+
furnished to do so, subject to the following conditions:
|
|
400
|
+
|
|
401
|
+
The above copyright notice and this permission notice shall be included in all
|
|
402
|
+
copies or substantial portions of the Software.
|
|
403
|
+
|
|
404
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
405
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
406
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
407
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
408
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
409
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
410
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Circle.d.ts","sourceRoot":"","sources":["../../src/components/Circle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAcxC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useMap } from '../context/MapContext';
|
|
3
|
+
export const Circle = (props) => {
|
|
4
|
+
const { registerLayer, unregisterLayer, updateLayer } = useMap();
|
|
5
|
+
const { id, center, radius, color, fillColor, fillOpacity, weight } = props;
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
registerLayer('circle', id, { center, radius, color, fillColor, fillOpacity, weight });
|
|
8
|
+
return () => unregisterLayer('circle', id);
|
|
9
|
+
}, []);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
updateLayer('circle', id, { center, radius, color, fillColor, fillOpacity, weight });
|
|
12
|
+
}, [id, center.lat, center.lng, radius, color, fillColor, fillOpacity, weight]);
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=Circle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Circle.js","sourceRoot":"","sources":["../../src/components/Circle.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/C,MAAM,CAAC,MAAM,MAAM,GAA0B,CAAC,KAAK,EAAE,EAAE;IACnD,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;IACjE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAE5E,SAAS,CAAC,GAAG,EAAE;QACX,aAAa,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;QACvF,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACX,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IACzF,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAEhF,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeoJSON.d.ts","sourceRoot":"","sources":["../../src/components/GeoJSON.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAa1C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useMap } from '../context/MapContext';
|
|
3
|
+
export const GeoJSON = ({ id, data, style, onPress }) => {
|
|
4
|
+
const { registerLayer, unregisterLayer, updateLayer } = useMap();
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
registerLayer('geojson', id, { data, style });
|
|
7
|
+
return () => unregisterLayer('geojson', id);
|
|
8
|
+
}, []);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
updateLayer('geojson', id, { data, style });
|
|
11
|
+
}, [id, data, style]);
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=GeoJSON.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeoJSON.js","sourceRoot":"","sources":["../../src/components/GeoJSON.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/C,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE;IAC5E,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;IAEjE,SAAS,CAAC,GAAG,EAAE;QACX,aAAa,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACX,WAAW,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAEtB,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../src/components/Heatmap.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAa1C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useMap } from '../context/MapContext';
|
|
3
|
+
export const Heatmap = ({ id, points, radius, blur, max }) => {
|
|
4
|
+
const { registerLayer, unregisterLayer, updateLayer } = useMap();
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
registerLayer('heatmap', id, { points, radius, blur, max });
|
|
7
|
+
return () => unregisterLayer('heatmap', id);
|
|
8
|
+
}, []);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
updateLayer('heatmap', id, { points, radius, blur, max });
|
|
11
|
+
}, [id, points, radius, blur, max]);
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=Heatmap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Heatmap.js","sourceRoot":"","sources":["../../src/components/Heatmap.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/C,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;IACjF,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;IAEjE,SAAS,CAAC,GAAG,EAAE;QACX,aAAa,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACX,WAAW,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9D,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAEpC,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MapContainerProps, LatLng } from '../types';
|
|
3
|
+
export interface MapContainerHandles {
|
|
4
|
+
fitBounds: (options?: any) => void;
|
|
5
|
+
centerToUserPosition: (position: LatLng) => void;
|
|
6
|
+
isUserPositionCentered: (position: LatLng) => boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const MapContainer: React.ForwardRefExoticComponent<MapContainerProps & React.RefAttributes<MapContainerHandles>>;
|
|
9
|
+
//# sourceMappingURL=MapContainer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapContainer.d.ts","sourceRoot":"","sources":["../../src/components/MapContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,EAAE,iBAAiB,EAA6B,MAAM,EAAE,MAAM,UAAU,CAAC;AAGhF,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACzD;AAED,eAAO,MAAM,YAAY,+FA6GvB,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React, { useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
import { WebView } from 'react-native-webview';
|
|
4
|
+
import MapContext from '../context/MapContext';
|
|
5
|
+
import { LEAFLET_HTML_CONTENT } from '../templates/LeafletHTML';
|
|
6
|
+
import { isEqual } from '../utils/deepEqual';
|
|
7
|
+
import { MapViewEvents } from '../types';
|
|
8
|
+
export const MapContainer = React.forwardRef(({ center, zoom = 13, isDark = false, backgroundColor = '#ffffff', dragEnabled = true, zoomEnabled = true, fitBounds = false, style, children, onMapReady, onMapClick, onMarkerClick, onUserGesture, onMoveEnd, }, ref) => {
|
|
9
|
+
const webViewRef = useRef(null);
|
|
10
|
+
const [isReady, setIsReady] = useState(false);
|
|
11
|
+
const [mapCenter, setMapCenter] = useState(center || null);
|
|
12
|
+
const sendMessage = useCallback((payload) => {
|
|
13
|
+
webViewRef.current?.injectJavaScript(`window.postMessage(${JSON.stringify(payload)}, '*');`);
|
|
14
|
+
}, []);
|
|
15
|
+
React.useImperativeHandle(ref, () => ({
|
|
16
|
+
fitBounds: (options) => {
|
|
17
|
+
sendMessage({ type: 'fitBounds', options });
|
|
18
|
+
},
|
|
19
|
+
centerToUserPosition: (pos) => {
|
|
20
|
+
sendMessage({ type: 'center', position: pos });
|
|
21
|
+
},
|
|
22
|
+
isUserPositionCentered: (pos) => {
|
|
23
|
+
if (!mapCenter)
|
|
24
|
+
return false;
|
|
25
|
+
return isEqual(mapCenter, pos);
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
const handleMessage = (event) => {
|
|
29
|
+
try {
|
|
30
|
+
const data = JSON.parse(event.nativeEvent.data);
|
|
31
|
+
switch (data.event) {
|
|
32
|
+
case MapViewEvents.MAP_READY:
|
|
33
|
+
setIsReady(true);
|
|
34
|
+
sendMessage({ type: 'init', center, zoom, isDark, background: backgroundColor, fitBounds });
|
|
35
|
+
onMapReady?.();
|
|
36
|
+
break;
|
|
37
|
+
case MapViewEvents.ON_MOVE_END:
|
|
38
|
+
setMapCenter(data.payload.mapCenterPosition);
|
|
39
|
+
onMoveEnd?.(data.payload.mapCenterPosition, data.payload.zoom, data.payload.bounds);
|
|
40
|
+
break;
|
|
41
|
+
case MapViewEvents.ON_MAP_CLICK:
|
|
42
|
+
onMapClick?.(data.payload.latlng);
|
|
43
|
+
break;
|
|
44
|
+
case MapViewEvents.ON_MARKER_CLICK:
|
|
45
|
+
onMarkerClick?.(data.payload.id);
|
|
46
|
+
break;
|
|
47
|
+
case MapViewEvents.ON_USER_GESTURE:
|
|
48
|
+
onUserGesture?.();
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
console.error('Error parsing map message:', e);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const registerLayer = (type, id, props) => {
|
|
57
|
+
sendMessage({ type, id, ...props });
|
|
58
|
+
};
|
|
59
|
+
const unregisterLayer = (type, id) => {
|
|
60
|
+
sendMessage({ type: `remove_${type}`, id });
|
|
61
|
+
};
|
|
62
|
+
const updateLayer = (type, id, props) => {
|
|
63
|
+
sendMessage({ type, id, ...props });
|
|
64
|
+
};
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
if (isReady) {
|
|
67
|
+
sendMessage({ type: 'theme', isDark, background: backgroundColor });
|
|
68
|
+
sendMessage({ type: 'fit_bounds_toggle', enabled: fitBounds });
|
|
69
|
+
}
|
|
70
|
+
}, [isDark, backgroundColor, fitBounds, isReady]);
|
|
71
|
+
return (<MapContext.Provider value={{ registerLayer, unregisterLayer, updateLayer, sendMessage }}>
|
|
72
|
+
<View style={[styles.container, style]}>
|
|
73
|
+
<WebView ref={webViewRef} source={{ html: LEAFLET_HTML_CONTENT }} style={[styles.webview, { backgroundColor: backgroundColor || 'transparent' }]} containerStyle={{ backgroundColor: backgroundColor || 'transparent' }} onMessage={handleMessage} javaScriptEnabled={true} domStorageEnabled={true} startInLoadingState={true} mixedContentMode="always" originWhitelist={['*']} bounces={false} scrollEnabled={false} overScrollMode="never"/>
|
|
74
|
+
{isReady && children}
|
|
75
|
+
</View>
|
|
76
|
+
</MapContext.Provider>);
|
|
77
|
+
});
|
|
78
|
+
const styles = StyleSheet.create({
|
|
79
|
+
container: {
|
|
80
|
+
flex: 1,
|
|
81
|
+
},
|
|
82
|
+
webview: {
|
|
83
|
+
flex: 1,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=MapContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapContainer.js","sourceRoot":"","sources":["../../src/components/MapContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAa,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,UAAU,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAqB,aAAa,EAAsB,MAAM,UAAU,CAAC;AAShF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAyC,CAAC,EAClF,MAAM,EACN,IAAI,GAAG,EAAE,EACT,MAAM,GAAG,KAAK,EACd,eAAe,GAAG,SAAS,EAC3B,WAAW,GAAG,IAAI,EAClB,WAAW,GAAG,IAAI,EAClB,SAAS,GAAG,KAAK,EACjB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,SAAS,GACZ,EAAE,GAAG,EAAE,EAAE;IACN,MAAM,UAAU,GAAG,MAAM,CAAU,IAAI,CAAC,CAAC;IACzC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgB,MAAM,IAAI,IAAI,CAAC,CAAC;IAE1E,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,OAAY,EAAE,EAAE;QAC7C,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAChC,sBAAsB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CACzD,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,KAAK,CAAC,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAClC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACnB,WAAW,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,oBAAoB,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,sBAAsB,EAAE,CAAC,GAAG,EAAE,EAAE;YAC5B,IAAI,CAAC,SAAS;gBAAE,OAAO,KAAK,CAAC;YAC7B,OAAO,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;KACJ,CAAC,CAAC,CAAC;IAEJ,MAAM,aAAa,GAAG,CAAC,KAAU,EAAE,EAAE;QACjC,IAAI,CAAC;YACD,MAAM,IAAI,GAAe,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC5D,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;gBACjB,KAAK,aAAa,CAAC,SAAS;oBACxB,UAAU,CAAC,IAAI,CAAC,CAAC;oBACjB,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC;oBAC5F,UAAU,EAAE,EAAE,CAAC;oBACf,MAAM;gBACV,KAAK,aAAa,CAAC,WAAW;oBAC1B,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;oBAC7C,SAAS,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACpF,MAAM;gBACV,KAAK,aAAa,CAAC,YAAY;oBAC3B,UAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBAClC,MAAM;gBACV,KAAK,aAAa,CAAC,eAAe;oBAC9B,aAAa,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACjC,MAAM;gBACV,KAAK,aAAa,CAAC,eAAe;oBAC9B,aAAa,EAAE,EAAE,CAAC;oBAClB,MAAM;YACd,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,KAAU,EAAE,EAAE;QAC3D,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,EAAE;QACjD,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,KAAU,EAAE,EAAE;QACzD,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;IAGF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,IAAI,OAAO,EAAE,CAAC;YACV,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,CAAC;YACpE,WAAW,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QACnE,CAAC;IACL,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAElD,OAAO,CACH,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CACrF;YAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACnC;gBAAA,CAAC,OAAO,CACJ,GAAG,CAAC,CAAC,UAAU,CAAC,CAChB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,CACvC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,eAAe,IAAI,aAAa,EAAE,CAAC,CAAC,CAC/E,cAAc,CAAC,CAAC,EAAE,eAAe,EAAE,eAAe,IAAI,aAAa,EAAE,CAAC,CACtE,SAAS,CAAC,CAAC,aAAa,CAAC,CACzB,iBAAiB,CAAC,CAAC,IAAI,CAAC,CACxB,iBAAiB,CAAC,CAAC,IAAI,CAAC,CACxB,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAC1B,gBAAgB,CAAC,QAAQ,CACzB,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CACvB,OAAO,CAAC,CAAC,KAAK,CAAC,CACf,aAAa,CAAC,CAAC,KAAK,CAAC,CACrB,cAAc,CAAC,OAAO,EAE1B;gBAAA,CAAC,OAAO,IAAI,QAAQ,CACxB;YAAA,EAAE,IAAI,CACV;QAAA,EAAE,UAAU,CAAC,QAAQ,CAAC,CACzB,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC7B,SAAS,EAAE;QACP,IAAI,EAAE,CAAC;KACV;IACD,OAAO,EAAE;QACL,IAAI,EAAE,CAAC;KACV;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MarkerProps, PopupProps } from '../types';
|
|
3
|
+
export declare const useMarker: () => {
|
|
4
|
+
setPopupOptions: (options: Partial<PopupProps>) => void;
|
|
5
|
+
} | null;
|
|
6
|
+
export declare const Marker: React.FC<MarkerProps>;
|
|
7
|
+
//# sourceMappingURL=Marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Marker.d.ts","sourceRoot":"","sources":["../../src/components/Marker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAMnD,eAAO,MAAM,SAAS;qBAHD,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI;QAGH,CAAC;AAEzD,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAoBxC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React, { useEffect, useState, createContext, useContext } from 'react';
|
|
2
|
+
import { useMap } from '../context/MapContext';
|
|
3
|
+
const MarkerContext = createContext(null);
|
|
4
|
+
export const useMarker = () => useContext(MarkerContext);
|
|
5
|
+
export const Marker = ({ id, position, icon, size, anchor, title, children }) => {
|
|
6
|
+
const { registerLayer, unregisterLayer, updateLayer } = useMap();
|
|
7
|
+
const [popupOptions, setPopupOptions] = useState({});
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
registerLayer('marker', id, { position, icon, size, anchor, title, ...popupOptions });
|
|
10
|
+
return () => unregisterLayer('marker', id);
|
|
11
|
+
}, []);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
updateLayer('marker', id, { position, icon, size, anchor, title, ...popupOptions });
|
|
14
|
+
}, [position.lat, position.lng, icon, size, anchor, title, JSON.stringify(popupOptions)]);
|
|
15
|
+
const contextValue = React.useMemo(() => ({ setPopupOptions }), [setPopupOptions]);
|
|
16
|
+
return (<MarkerContext.Provider value={contextValue}>
|
|
17
|
+
{children}
|
|
18
|
+
</MarkerContext.Provider>);
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=Marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Marker.js","sourceRoot":"","sources":["../../src/components/Marker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/C,MAAM,aAAa,GAAG,aAAa,CAEzB,IAAI,CAAC,CAAC;AAEhB,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAEzD,MAAM,CAAC,MAAM,MAAM,GAA0B,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;IACnG,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;IACjE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAsB,EAAE,CAAC,CAAC;IAE1E,SAAS,CAAC,GAAG,EAAE;QACX,aAAa,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC,CAAC;QACtF,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACX,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC,CAAC;IACxF,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAE1F,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEnF,OAAO,CACH,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACxC;YAAA,CAAC,QAAQ,CACb;QAAA,EAAE,aAAa,CAAC,QAAQ,CAAC,CAC5B,CAAC;AACN,CAAC,CAAC"}
|