@tracktor/map 1.6.4 β†’ 1.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +640 -73
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,29 +1,62 @@
1
- # πŸ“ MarkerMap - React Map Library
1
+ # πŸ—ΊοΈ @tracktor/map
2
2
 
3
- **MarkerMap** is a React library built on top of Mapbox GL JS. It simplifies rendering interactive maps with customizable markers in your React applications.
3
+ A modern, lightweight React map library built on top of Mapbox GL JS and react-map-gl. Designed for simplicity, flexibility, and visual elegance.
4
4
 
5
- ## πŸš€ Installation
5
+ Easily combine markers, routes, GeoJSON features, isochrones, and nearest-point calculations β€” all with a declarative, type-safe API.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@tracktor/map.svg)](https://www.npmjs.com/package/@tracktor/map)
8
+ [![License](https://img.shields.io/badge/license-UNLICENSED-red.svg)](LICENSE)
9
+
10
+ ---
6
11
 
12
+ ## πŸš€ Installation
7
13
  ```bash
8
14
  npm install @tracktor/map
9
15
  ```
10
16
 
11
17
  or
12
-
13
18
  ```bash
14
19
  yarn add @tracktor/map
15
20
  ```
16
21
 
17
- ## πŸ“¦ Dependencies
22
+ or
23
+ ```bash
24
+ bun add @tracktor/map
25
+ ```
26
+
27
+ ---
28
+
29
+ ## βš™οΈ Requirements
30
+
31
+ | Dependency | Version | Purpose |
32
+ |------------|---------|---------|
33
+ | `react` | 17+ / 18+ / 19+ | Core React runtime |
34
+ | `react-dom` | 17+ / 18+ / 19+ | React DOM rendering |
35
+ | `mapbox-gl` | β‰₯3.0.0 | Map rendering engine |
36
+ | `@tracktor/design-system` | β‰₯4.0.0 | UI theming and components |
37
+ | `@mui/icons-material` | * | Material UI icons |
38
+ | `@mui/x-license` | * | MUI X license integration |
18
39
 
19
- This library depends on:
40
+ πŸͺΆ **You'll also need a Mapbox access token** to render maps. Get one at [mapbox.com](https://account.mapbox.com/access-tokens/).
20
41
 
21
- - `@tracktor/design-system` for theming and styling
22
- - `mapbox-gl` for map rendering
23
- - React 19+
42
+ ---
24
43
 
25
- ## πŸ”§ Usage
44
+ ## ✨ Features
26
45
 
46
+ βœ… **Declarative API** β€” manage complex map interactions with simple props
47
+ βœ… **Markers & Popups** β€” customizable React components or image-based icons
48
+ βœ… **Routing & Isochrones** β€” visualize travel-time areas or compute optimal routes
49
+ βœ… **GeoJSON Layers** β€” render vector data dynamically
50
+ βœ… **Nearest Marker Search** β€” find and highlight closest points instantly
51
+ βœ… **Type-safe API** β€” full TypeScript support with smart IntelliSense
52
+ βœ… **Responsive Design** β€” automatically adapts to any container or screen size
53
+ βœ… **Built for performance** β€” minimal re-renders, efficient map updates
54
+ βœ… **Multiple Routing Engines** β€” supports both OSRM (free) and Mapbox Directions API
55
+ βœ… **Flexible Map Styles** β€” works with Mapbox styles, OpenStreetMap, or custom raster tiles
56
+
57
+ ---
58
+
59
+ ## 🧩 Quick Start
27
60
  ```tsx
28
61
  import { MapProvider, MarkerMap } from "@tracktor/map";
29
62
 
@@ -33,82 +66,616 @@ const markers = [
33
66
  lng: 2.3522,
34
67
  lat: 48.8566,
35
68
  Tooltip: <div>Paris</div>,
36
- iconImage: "marker-icon.png",
37
- size: 40,
38
- onClick: () => alert("Marker clicked!"),
69
+ color: "primary",
70
+ variant: "default",
71
+ },
72
+ {
73
+ id: 2,
74
+ lng: -0.1276,
75
+ lat: 51.5074,
76
+ Tooltip: <div>London</div>,
77
+ color: "secondary",
78
+ variant: "default",
39
79
  },
40
80
  ];
41
81
 
42
- <MapProvider licenseMuiX="your-muix-licence" licenceMapbox="your-mapbox-licence">
43
- <MarkerMap
82
+ function App() {
83
+ return (
84
+ <MapProvider
85
+ licenseMuiX="your-muix-license"
86
+ licenceMapbox="your-mapbox-token"
87
+ >
88
+ <MarkerMap
89
+ markers={markers}
90
+ center={[2.3522, 48.8566]}
91
+ zoom={5}
92
+ fitBounds
93
+ height={500}
94
+ width="100%"
95
+ onMapClick={(lng, lat, marker) => {
96
+ console.log("Clicked at:", lng, lat);
97
+ if (marker) console.log("Marker clicked:", marker);
98
+ }}
99
+ />
100
+ </MapProvider>
101
+ );
102
+ }
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 🧭 Components Overview
108
+
109
+ ### `MapProvider`
110
+
111
+ Wraps your map components and injects required providers (theme, tokens, MUI X license).
112
+
113
+ **Required Props:**
114
+ - `licenseMuiX` β€” Your MUI X license key
115
+ - `licenceMapbox` β€” Your Mapbox access token
116
+ ```tsx
117
+ <MapProvider
118
+ licenseMuiX="your-license"
119
+ licenceMapbox="your-token"
120
+ >
121
+ {/* Your map components */}
122
+ </MapProvider>
123
+ ```
124
+
125
+ ### `MapView` / `MarkerMap`
126
+
127
+ Main map component that handles:
128
+ - Marker rendering with custom icons or React components
129
+ - Interactive popups with hover/click modes
130
+ - Automatic bounds fitting
131
+ - Map click events
132
+ - Responsive container sizing
133
+
134
+ ### Specialized Components
135
+
136
+ - **`RouteMap`** β†’ Draw routes between two points using OSRM or Mapbox
137
+ - **`IsochroneMap`** β†’ Compute and display travel-time polygons
138
+ - **`FeatureMap`** β†’ Display custom GeoJSON layers with styling
139
+
140
+ ---
141
+
142
+ ## 🧱 Props Reference
143
+
144
+ ### `MapView` Props
145
+
146
+ #### Core Map Props
147
+
148
+ | Prop | Type | Default | Description |
149
+ |------|------|---------|-------------|
150
+ | `center` | `[lng, lat]` | `[2.3522, 48.8566]` | Initial map center coordinates |
151
+ | `zoom` | `number` | `5` | Initial zoom level (0-22) |
152
+ | `width` | `string \| number` | `"100%"` | Map container width |
153
+ | `height` | `string \| number` | `300` | Map container height |
154
+ | `loading` | `boolean` | `false` | Show skeleton loader |
155
+ | `square` | `boolean` | `false` | Enforce 1:1 aspect ratio |
156
+ | `containerStyle` | `SxProps` | `undefined` | Custom MUI sx styles |
157
+
158
+ #### Map Appearance
159
+
160
+ | Prop | Type | Default | Description |
161
+ |------|------|---------|-------------|
162
+ | `theme` | `"light" \| "dark"` | `"light"` | Map color theme |
163
+ | `baseMapView` | `"street" \| "satellite"` | `"street"` | Base map layer type |
164
+ | `mapStyle` | `string` | - | Custom Mapbox style URL |
165
+ | `projection` | `ProjectionSpecification` | `"mercator"` | Map projection system |
166
+
167
+ #### Interaction Props
168
+
169
+ | Prop | Type | Default | Description |
170
+ |------|------|---------|-------------|
171
+ | `cooperativeGestures` | `boolean` | `true` | Require modifier key for zoom/pan |
172
+ | `doubleClickZoom` | `boolean` | `true` | Enable double-click to zoom |
173
+ | `onMapClick` | `(lng, lat, marker?) => void` | - | Callback for map clicks |
174
+
175
+ #### Marker Props
176
+
177
+ | Prop | Type | Default | Description |
178
+ |------|------|---------|-------------|
179
+ | `markers` | `MarkerProps[]` | `[]` | Array of markers to display |
180
+ | `openPopup` | `string \| number` | `undefined` | ID of marker with open popup |
181
+ | `openPopupOnHover` | `boolean` | `false` | Open popups on hover instead of click |
182
+ | `popupMaxWidth` | `string` | `"300px"` | Maximum popup width |
183
+
184
+ #### Bounds & Animation
185
+
186
+ | Prop | Type | Default | Description |
187
+ |------|------|---------|-------------|
188
+ | `fitBounds` | `boolean` | `true` | Auto-fit map to show all markers |
189
+ | `fitBoundsPadding` | `number` | `0` | Padding (px) around fitted bounds |
190
+ | `fitBoundDuration` | `number` | `500` | Animation duration (ms) |
191
+ | `disableAnimation` | `boolean` | `false` | Disable all animations |
192
+ | `fitBoundsAnimationKey` | `unknown` | - | Change to re-trigger fit bounds |
193
+
194
+ ---
195
+
196
+ ### Marker Props (`MarkerProps`)
197
+
198
+ | Prop | Type | Required | Description |
199
+ |------|------|----------|-------------|
200
+ | `id` | `string \| number` | βœ… | Unique marker identifier |
201
+ | `lng` | `number` | βœ… | Longitude coordinate |
202
+ | `lat` | `number` | βœ… | Latitude coordinate |
203
+ | `Tooltip` | `ReactNode` | - | Content for popup/tooltip |
204
+ | `IconComponent` | `React.ComponentType` | - | Custom React icon component |
205
+ | `iconProps` | `object` | - | Props passed to IconComponent |
206
+ | `color` | `string` | - | Marker color (MUI palette) |
207
+ | `variant` | `string` | - | Marker style variant |
208
+
209
+ **Example with custom icon:**
210
+ ```tsx
211
+ import LocationOnIcon from '@mui/icons-material/LocationOn';
212
+
213
+ const marker = {
214
+ id: 1,
215
+ lng: 2.3522,
216
+ lat: 48.8566,
217
+ IconComponent: LocationOnIcon,
218
+ iconProps: { fontSize: 'large', color: 'error' },
219
+ Tooltip: <div>Custom Icon Marker</div>
220
+ };
221
+ ```
222
+
223
+ ---
224
+
225
+ ### Routing Props
226
+
227
+ Add a route between two points by providing `from` and `to` coordinates.
228
+
229
+ | Prop | Type | Default | Description |
230
+ |------|------|---------|-------------|
231
+ | `from` | `[lng, lat]` | - | Route starting point |
232
+ | `to` | `[lng, lat]` | - | Route ending point |
233
+ | `profile` | `"driving" \| "walking" \| "cycling"` | `"driving"` | Transportation mode |
234
+ | `engine` | `"OSRM" \| "Mapbox"` | `"OSRM"` | Routing service to use |
235
+ | `itineraryLineStyle` | `{ color, width, opacity }` | `{ color: "#3b82f6", width: 4, opacity: 0.8 }` | Route line appearance |
236
+
237
+ **Example:**
238
+ ```tsx
239
+ <MapView
240
+ from={[2.3522, 48.8566]} // Paris
241
+ to={[-0.1276, 51.5074]} // London
242
+ profile="driving"
243
+ engine="OSRM"
244
+ itineraryLineStyle={{
245
+ color: "#10b981",
246
+ width: 5,
247
+ opacity: 0.9
248
+ }}
249
+ />
250
+ ```
251
+
252
+ ---
253
+
254
+ ### Nearest Marker Search
255
+
256
+ Find and highlight the closest marker to a given point within a maximum distance.
257
+
258
+ | Prop | Type | Description |
259
+ |------|------|-------------|
260
+ | `findNearestMarker.origin` | `[lng, lat]` | Starting point for search |
261
+ | `findNearestMarker.destinations` | `Array<{lng, lat, id}>` | Candidate destinations |
262
+ | `findNearestMarker.maxDistanceMeters` | `number` | Maximum search radius |
263
+ | `onNearestFound` | `(id, coords, distance) => void` | Callback with nearest result |
264
+
265
+ **Example:**
266
+ ```tsx
267
+ <MapView
268
+ findNearestMarker={{
269
+ origin: [2.3522, 48.8566],
270
+ destinations: markers.map(m => ({
271
+ lng: m.lng,
272
+ lat: m.lat,
273
+ id: m.id
274
+ })),
275
+ maxDistanceMeters: 5000,
276
+ }}
277
+ onNearestFound={(id, coords, distance) => {
278
+ console.log(`Nearest: ${id} at ${distance}m`);
279
+ }}
280
+ />
281
+ ```
282
+
283
+ ---
284
+
285
+ ### Isochrone Props
286
+
287
+ Compute and display areas reachable within specific time intervals.
288
+
289
+ | Prop | Type | Description |
290
+ |------|------|-------------|
291
+ | `isochrone.origin` | `[lng, lat]` | Center point for isochrone |
292
+ | `isochrone.profile` | `"driving" \| "walking" \| "cycling"` | Transportation mode |
293
+ | `isochrone.intervals` | `number[]` | Time intervals in minutes |
294
+ | `isochrone.onIsochroneLoaded` | `(data) => void` | Callback with GeoJSON result |
295
+
296
+ **Example:**
297
+ ```tsx
298
+ <MapView
299
+ isochrone={{
300
+ origin: [2.3522, 48.8566],
301
+ profile: "driving",
302
+ intervals: [5, 10, 15, 20], // 5, 10, 15, 20 minutes
303
+ onIsochroneLoaded: (geojson) => {
304
+ console.log("Isochrone data:", geojson);
305
+ }
306
+ }}
307
+ />
308
+ ```
309
+
310
+ ---
311
+
312
+ ### GeoJSON Features
313
+
314
+ Display custom vector features like polygons, lines, or points.
315
+
316
+ | Prop | Type | Description |
317
+ |------|------|-------------|
318
+ | `features` | `Feature \| Feature[] \| FeatureCollection` | GeoJSON data to render |
319
+
320
+ **Example:**
321
+ ```tsx
322
+ <MapView
323
+ features={{
324
+ type: "Feature",
325
+ geometry: {
326
+ type: "LineString",
327
+ coordinates: [
328
+ [2.3, 48.8],
329
+ [2.4, 48.9],
330
+ [2.5, 48.85]
331
+ ]
332
+ },
333
+ properties: {
334
+ color: "#ef4444"
335
+ }
336
+ }}
337
+ />
338
+ ```
339
+
340
+ ---
341
+
342
+ ## 🧠 Advanced Use Cases
343
+
344
+ ### 🧭 Real-time GPS Tracking
345
+ ```tsx
346
+ function LiveTracking() {
347
+ const [position, setPosition] = useState([2.3522, 48.8566]);
348
+
349
+ useEffect(() => {
350
+ const watchId = navigator.geolocation.watchPosition((pos) => {
351
+ setPosition([pos.coords.longitude, pos.coords.latitude]);
352
+ });
353
+ return () => navigator.geolocation.clearWatch(watchId);
354
+ }, []);
355
+
356
+ return (
357
+ <MapView
358
+ markers={[{
359
+ id: 'current',
360
+ lng: position[0],
361
+ lat: position[1],
362
+ Tooltip: <div>You are here</div>
363
+ }]}
364
+ center={position}
365
+ zoom={15}
366
+ fitBounds={false}
367
+ />
368
+ );
369
+ }
370
+ ```
371
+
372
+ ### πŸ”„ Dynamic Data with React Query
373
+ ```tsx
374
+ import { useQuery } from '@tanstack/react-query';
375
+
376
+ function DynamicMarkers() {
377
+ const { data: markers } = useQuery({
378
+ queryKey: ['locations'],
379
+ queryFn: fetchLocations,
380
+ refetchInterval: 5000 // Refresh every 5s
381
+ });
382
+
383
+ return (
384
+ <MapView
44
385
  markers={markers}
45
- center={[2.3522, 48.8566]}
46
- zoom={10}
47
386
  fitBounds
48
- height={400}
49
- width="100%"
387
+ fitBoundsAnimationKey={markers?.length}
50
388
  />
51
- </MapProvider>
389
+ );
390
+ }
52
391
  ```
53
392
 
54
- ## 🧩 Props
55
-
56
- ### MarkerMap Props
57
-
58
- | Prop | Type | Description |
59
- |--------------------|--------------------------------------|--------------------------------------------------------|
60
- | `markers` | `MarkerProps[]` | List of markers to display |
61
- | `center` | `LngLatLike` or `[number, number]` | Initial map center coordinates |
62
- | `zoom` | `number` | Initial zoom level |
63
- | `fitBounds` | `boolean` | Automatically fit the map to the bounds of all markers |
64
- | `fitBoundsPadding` | `number` | Padding around markers when fitting bounds |
65
- | `zoomFlyFrom` | `number` | Zoom level to fly in from |
66
- | `popupMaxWidth` | `string` | Max width for popups |
67
- | `width` | `number` or `string` | Map width |
68
- | `height` | `number` or `string` | Map height |
69
- | `loading` | `boolean` | Whether to show a loading state |
70
- | `markerImageURL` | `string` | Default marker image URL |
71
- | `containerStyle` | `SxProps` | Custom styles for the map container |
72
- | `disableFlyTo` | `boolean` | Disable flyTo animation on marker click |
73
- | `flyToDuration` | `number` | Duration of the flyTo animation |
74
- | `fitBoundDuration` | `number` | Duration of the fitBounds animation |
75
- | `square` | `boolean` | Forces the map to be square-shaped |
76
- | `openPopup` | `number` or `string` | ID of the marker with an open popup |
77
- | `openPopupOnHover` | `boolean` | Automatically open popups on marker hover |
78
- | `onMapClick` | `(lng: number, lat: number) => void` | Callback triggered when clicking on the map |
79
-
80
- ### MarkerProps
81
-
82
- | Prop | Type | Description |
83
- |-------------|----------------------|---------------------------------------------------------------|
84
- | `id` | `number` or `string` | Unique marker identifier |
85
- | `lng` | `number` | Longitude |
86
- | `lat` | `number` | Latitude |
87
- | `Tooltip` | `ReactNode` | Tooltip content displayed in a popup |
88
- | `iconImage` | `string` | Image URL used as marker icon |
89
- | `size` | `number` | Marker size in pixels |
90
- | `zIndex` | `number` | Z-index to control stacking order |
91
- | `onClick` | `() => void` | Function triggered on marker click |
92
- | `type` | `string` | Custom marker type (optional, for filtering or styling) |
93
- | `name` | `string` | Name of the marker |
94
- | `Icon` | `ReactNode` | Custom React component to render instead of default image |
95
-
96
-
97
- ## πŸ§‘β€πŸ’» Contributing
98
-
99
- Contributions are welcome! Please follow the coding conventions and include tests when necessary.
393
+ ### 🎨 Custom Marker Components
394
+ ```tsx
395
+ function CustomMarker({ isActive, count }) {
396
+ return (
397
+ <Box
398
+ sx={{
399
+ width: 40,
400
+ height: 40,
401
+ borderRadius: '50%',
402
+ bgcolor: isActive ? 'success.main' : 'grey.500',
403
+ display: 'flex',
404
+ alignItems: 'center',
405
+ justifyContent: 'center',
406
+ color: 'white',
407
+ fontWeight: 'bold',
408
+ border: '2px solid white',
409
+ boxShadow: 2
410
+ }}
411
+ >
412
+ {count}
413
+ </Box>
414
+ );
415
+ }
100
416
 
101
- ## πŸ“„ License
417
+ <MapView
418
+ markers={[{
419
+ id: 1,
420
+ lng: 2.3522,
421
+ lat: 48.8566,
422
+ IconComponent: CustomMarker,
423
+ iconProps: { isActive: true, count: 5 }
424
+ }]}
425
+ />
426
+ ```
427
+
428
+ ### πŸ—ΊοΈ Multi-Route Comparison
429
+ ```tsx
430
+ <MapView
431
+ features={[
432
+ {
433
+ type: "Feature",
434
+ geometry: {
435
+ type: "LineString",
436
+ coordinates: route1
437
+ },
438
+ properties: { color: "#3b82f6" }
439
+ },
440
+ {
441
+ type: "Feature",
442
+ geometry: {
443
+ type: "LineString",
444
+ coordinates: route2
445
+ },
446
+ properties: { color: "#ef4444" }
447
+ }
448
+ ]}
449
+ />
450
+ ```
451
+
452
+ ### 🎯 Click-to-Add Markers
453
+ ```tsx
454
+ function InteractiveMap() {
455
+ const [markers, setMarkers] = useState([]);
456
+
457
+ const handleMapClick = (lng, lat) => {
458
+ setMarkers(prev => [...prev, {
459
+ id: Date.now(),
460
+ lng,
461
+ lat,
462
+ Tooltip: <div>Point {markers.length + 1}</div>
463
+ }]);
464
+ };
465
+
466
+ return (
467
+ <MapView
468
+ markers={markers}
469
+ onMapClick={handleMapClick}
470
+ />
471
+ );
472
+ }
473
+ ```
474
+
475
+ ---
476
+
477
+ ## πŸ’‘ Tips & Best Practices
478
+
479
+ ### Performance Optimization
480
+
481
+ - **Memoize marker data** to prevent unnecessary re-renders
482
+ - **Use `fitBoundsAnimationKey`** to control when bounds recalculate
483
+ - **Disable animations** for large datasets: `disableAnimation={true}`
484
+ - **Debounce dynamic updates** when tracking real-time data
485
+
486
+ ### UX Improvements
487
+
488
+ - Combine `openPopupOnHover` and `disableAnimation` for smooth interactions
489
+ - Use `fitBoundsPadding` to ensure markers aren't at screen edges
490
+ - Set appropriate `popupMaxWidth` for mobile responsiveness
491
+ - Provide visual feedback with custom `IconComponent` states
492
+
493
+ ### Routing Best Practices
494
+
495
+ - **Use OSRM** (free) for basic routing needs
496
+ - **Use Mapbox** for production apps requiring SLA and support
497
+ - Cache route results to minimize API calls
498
+ - Handle network errors gracefully
499
+
500
+ ---
501
+
502
+ ## πŸ§‘β€πŸ’» Development
503
+
504
+ ### Prerequisites
505
+
506
+ - **Bun** β‰₯1.1.0 (recommended) or Node.js 18+
507
+ - Git
508
+
509
+ ### Setup
510
+ ```bash
511
+ # Clone the repository
512
+ git clone https://github.com/tracktor-tech/tracktor-map.git
513
+ cd tracktor-map
514
+
515
+ # Install dependencies
516
+ bun install
517
+
518
+ # Start development sandbox
519
+ bun run sandbox
520
+ # or
521
+ bun run dev:sandbox
522
+ ```
102
523
 
103
- MIT Β© [Kevin Graff / Tracktor]
524
+ ### Available Scripts
104
525
 
526
+ | Command | Description |
527
+ |---------|-------------|
528
+ | `bun run sandbox` | Start interactive development playground |
529
+ | `bun run build` | Build library for production |
530
+ | `bun run build:sandbox` | Build sandbox demo site |
531
+ | `bun run deploy:sandbox` | Deploy sandbox to GitHub Pages |
532
+ | `bun run lint` | Check code quality and types |
533
+ | `bun run lint:fix` | Auto-fix linting issues |
534
+ | `bun run test` | Run test suite |
535
+ | `bun run test:watch` | Run tests in watch mode |
536
+ | `bun run version` | Bump version with changelog |
537
+ | `bun run release` | Build and publish to npm |
105
538
 
106
- ## GH-Pages
107
- This project uses GitHub Pages for documentation hosting. To deploy the documentation, run:
539
+ ### Project Structure
540
+ ```
541
+ @tracktor/map/
542
+ β”œβ”€β”€ src/
543
+ β”‚ β”œβ”€β”€ components/ # Reusable map and UI components (Marker, Popup, etc.)
544
+ β”‚ β”œβ”€β”€ constants/ # Shared configuration values and styling constants
545
+ β”‚ β”œβ”€β”€ context/ # React context providers (e.g. map state)
546
+ β”‚ β”œβ”€β”€ features/ # Core map features (routes, isochrones, nearest, etc.)
547
+ β”‚ β”œβ”€β”€ services/ # External APIs and utility services
548
+ β”‚ β”œβ”€β”€ types/ # TypeScript interfaces and types
549
+ β”‚ β”œβ”€β”€ utils/ # Generic helpers and formatting functions
550
+ β”‚ └── main.ts # Library entry point
551
+ β”‚
552
+ β”œβ”€β”€ sandbox/ # Development playground (example app & live demos)
553
+ β”‚ β”œβ”€β”€ context/ # Demo context providers
554
+ β”‚ β”œβ”€β”€ examples/ # Interactive usage examples
555
+ β”‚ β”œβ”€β”€ features/ # Components used in the docs/demo
556
+ β”‚ β”œβ”€β”€ public/ # Static assets (images, previews, etc.)
557
+ β”‚ β”œβ”€β”€ App.tsx # Sandbox root component
558
+ β”‚ └── index.tsx # Sandbox entry file
559
+ β”‚
560
+ └── test/ # Unit and integration tests
561
+ ```
562
+
563
+ ### Testing
564
+ ```bash
565
+ # Run all tests
566
+ bun test
567
+
568
+ # Watch mode
569
+ bun test:watch
570
+
571
+ # Run specific test file
572
+ bun test src/components/MapView.test.tsx
573
+ ```
574
+
575
+ ### Contributing
576
+
577
+ We welcome contributions! Please:
578
+
579
+ 1. Fork the repository
580
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
581
+ 3. Make your changes
582
+ 4. Run tests and linting (`bun run test && bun run lint`)
583
+ 5. Commit your changes (`git commit -m 'Add amazing feature'`)
584
+ 6. Push to the branch (`git push origin feature/amazing-feature`)
585
+ 7. Open a Pull Request
586
+
587
+ **Code Style:**
588
+ - Follow existing patterns and conventions
589
+ - Use TypeScript for all new code
590
+ - Add tests for new features
591
+ - Update documentation as needed
592
+
593
+ ---
594
+
595
+ ## πŸ“˜ Documentation & Examples
596
+
597
+ Explore interactive examples and comprehensive API documentation:
598
+
599
+ πŸ‘‰ **[Live Documentation & Sandbox](https://tracktor.github.io/map)**
600
+
601
+ The sandbox includes:
602
+ - Interactive code examples
603
+ - Live preview of all features
604
+ - Copy-paste ready snippets
605
+ - API reference with search
606
+
607
+ ---
608
+
609
+ ## πŸ“¦ Publishing & Deployment
610
+
611
+ ### Publish to npm
612
+ ```bash
613
+ # Update version and generate changelog
614
+ bun run version
108
615
 
616
+ # Build and publish
617
+ bun run release
109
618
  ```
110
- bun run deploy:example
619
+
620
+ ### Deploy Sandbox to GitHub Pages
621
+ ```bash
622
+ bun run deploy:sandbox
111
623
  ```
112
- This will build the documentation and push it to the `gh-pages` branch.
113
624
 
114
- GH-Pages URL: https://tracktor.github.io/map/
625
+ This will:
626
+ 1. Build the sandbox with production optimizations
627
+ 2. Generate a 404.html for client-side routing
628
+ 3. Push to the `gh-pages` branch
629
+ 4. Update the live documentation site
630
+
631
+ ---
632
+
633
+ ## πŸ”§ Troubleshooting
634
+
635
+ ### Common Issues
636
+
637
+ **Map not rendering:**
638
+ - Verify your Mapbox token is valid
639
+ - Check browser console for errors
640
+ - Ensure mapbox-gl CSS is imported
641
+
642
+ **TypeScript errors:**
643
+ - Run `bun install` to update type definitions
644
+ - Check peer dependency versions match
645
+
646
+ **Performance issues:**
647
+ - Reduce marker count or use clustering
648
+ - Disable animations for large datasets
649
+ - Memoize marker data
650
+
651
+ ### Getting Help
652
+
653
+ - πŸ“– Check the [documentation](https://tracktor.github.io/map)
654
+ - πŸ› [Report bugs](https://github.com/tracktor-tech/tracktor-map/issues)
655
+ - πŸ’¬ Join discussions in GitHub Discussions
656
+
657
+ ---
658
+
659
+ ## πŸ“„ License
660
+
661
+ **UNLICENSED** β€” This package is proprietary software.
662
+ Β© [Tracktor β€” Kevin Graff]
663
+
664
+ ---
665
+
666
+ ## 🧭 Links
667
+
668
+ - πŸ“¦ **npm**: [@tracktor/map](https://www.npmjs.com/package/@tracktor/map)
669
+ - πŸ’» **GitHub**: [tracktor-tech/tracktor-map](https://github.com/tracktor-tech/tracktor-map)
670
+ - 🌐 **Docs**: [tracktor.github.io/map](https://tracktor.github.io/map)
671
+ - 🎨 **Design System**: [@tracktor/design-system](https://www.npmjs.com/package/@tracktor/design-system)
672
+
673
+ ---
674
+
675
+ ## πŸ™ Acknowledgments
676
+
677
+ Built with:
678
+ - [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/) β€” Powerful map rendering
679
+ - [react-map-gl](https://visgl.github.io/react-map-gl/) β€” React wrapper for Mapbox
680
+ - [OSRM](http://project-osrm.org/) β€” Free routing engine
681
+ - [@tracktor/design-system](https://www.npmjs.com/package/@tracktor/design-system) β€” UI components
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A React library to easily display map with multiple tools",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
- "version": "1.6.4",
6
+ "version": "1.6.5",
7
7
  "type": "module",
8
8
  "main": "dist/main.umd.cjs",
9
9
  "module": "dist/main.js",