# @1amageek/mapkit A React wrapper for Apple's MapKit JS, providing a seamless way to integrate Apple Maps into your React applications. ## Features - πŸ—ΊοΈ Full TypeScript support - πŸ”„ React component lifecycle integration - πŸ“ Support for markers, custom annotations, and overlays - 🎨 Customizable map styling and controls - πŸ”’ Automatic token management and refresh - 🎯 Built-in error handling - πŸ’« Smooth animations and transitions - πŸ–±οΈ Comprehensive event handling for map interactions, annotations, and user location ## Installation ```bash npm install @1amageek/mapkit ``` ## Prerequisites You'll need: 1. An Apple Developer account 2. A Maps ID from the Apple Developer portal 3. A token generation endpoint in your backend ## Basic Usage First, wrap your application with the `MapKitProvider`: ```tsx import { MapKitProvider } from '@1amageek/mapkit'; const App = () => { const fetchToken = async () => { // Fetch your MapKit JS token from your server const response = await fetch('your-token-endpoint'); const data = await response.json(); return { token: data.token, expiresAt: data.expiresAt // Unix timestamp in seconds }; }; return ( ); }; ``` Then use the Map component: ```tsx import { Map, MarkerAnnotation } from '@1amageek/mapkit'; ``` ## Event Handling The library supports a wide range of events for the map, annotations, and user location: ### Map Events The `Map` component emits various events related to map display and interaction: - `onRegionChangeStart`: Triggered when the map region starts changing. - `onRegionChangeEnd`: Triggered when the map region finishes changing. - `onRotationStart`: Triggered when the map starts rotating. - `onRotationEnd`: Triggered when the map finishes rotating. - `onScrollStart`: Triggered when the map starts scrolling. - `onScrollEnd`: Triggered when the map finishes scrolling. - `onZoomStart`: Triggered when the map starts zooming. - `onZoomEnd`: Triggered when the map finishes zooming. - `onMapTypeChange`: Triggered when the map type changes (e.g., from satellite to standard). - `onSingleTap`: Triggered when the map is tapped once. - `onDoubleTap`: Triggered when the map is double-tapped. - `onLongPress`: Triggered when the map is long-pressed. ### Annotation Events - `onSelect`: Triggered when an annotation is selected - `onDeselect`: Triggered when an annotation is deselected - `onDrag`: Triggered while an annotation is being dragged, providing real-time updates. - `onDragStart`: Triggered when starting to drag an annotation - `onDragEnd`: Triggered when finishing dragging an annotation ### User Location Events - `onUserLocationChange`: Triggered when the user's location changes. Provides the new coordinate and timestamp. - `onUserLocationError`: Triggered when an error occurs while trying to retrieve the user's location. Example usage with events: ```tsx import { Map, MarkerAnnotation } from '@1amageek/mapkit'; const MapComponent = () => { return ( ) => { console.log("Region change start", event); }} onRegionChangeEnd={(event: mapkit.EventBase) => { console.log("Region change end", event); }} region={{ center: { latitude: 35.6812, longitude: 139.7671 }, span: { latitudeDelta: 0.1, longitudeDelta: 0.1 } }} > ); }; ``` ## Event Types ```typescript interface AnnotationEventHandlers { onSelect?: (event: mapkit.EventBase) => void; onDeselect?: (event: mapkit.EventBase) => void; onDrag?: (event: mapkit.EventBase) => void; onDragStart?: (event: mapkit.EventBase) => void; onDragEnd?: (event: mapkit.EventBase) => void; } ``` ## Usage Examples ### Basic Marker Annotation with Events ```tsx { // Event when user clicks/taps the annotation const annotation = event.target; console.log('Selected:', annotation.title); console.log('At coordinate:', annotation.coordinate); }} onDrag={(event) => { // Real-time coordinate updates during drag console.log('Current position:', event.coordinate); }} onDragEnd={(event) => { // Final location after drag ends const { latitude, longitude } = event.coordinate; console.log('Final position:', { latitude, longitude }); }} /> ``` ### Custom Annotation with Complex Interaction ```tsx { // Access to DOM event and screen coordinates console.log('Click position:', event.pointOnPage); console.log('DOM event:', event.domEvent); }} callout={{ calloutContentForAnnotation: (annotation) => (

{annotation.title}

) }} >
{/* Your custom marker content */}
``` ### Multiple Annotations with Shared Event Handler ```tsx const MapWithAnnotations = () => { const handleAnnotationSelect = (event: mapkit.EventBase) => { // Common handler for all annotations const { title, data } = event.target; console.log('Selected location:', title); console.log('Custom data:', data); }; return ( {locations.map((location) => ( ))} ); }; ``` ### Image Annotation with Clustering ```tsx { if (event.target.memberAnnotations) { // This is a cluster console.log('Cluster size:', event.target.memberAnnotations.length); } else { // Single annotation console.log('Selected image annotation'); } }} /> ``` These event handlers are available for all annotation types (`MarkerAnnotation`, `ImageAnnotation`, `CustomAnnotation`). # Advanced Features ### Custom Annotations Create custom annotations with your own React components: ```tsx import { CustomAnnotation } from '@1amageek/mapkit'; const CustomPin = () => (
Custom Pin
); ``` ### Overlays Add various types of overlays to your map: ```tsx import { CircleOverlay, PolylineOverlay, PolygonOverlay } from '@1amageek/mapkit'; const MapWithOverlays = () => ( ); ``` ### Error Handling The library provides built-in error handling: ```tsx const MapComponent = () => ( { console.error('Map error:', error); }} errorComponent={
Failed to load map
} loadingComponent={
Loading map...
} /> ); ``` ## API Reference ### MapKitProvider Props | Prop | Type | Required | Description | |------|------|----------|-------------| | fetchToken | () => Promise | Yes | Function to fetch MapKit JS token | | options | MapKitInitOptions | No | Initialization options | | onError | (error: MapKitError) => void | No | Error handler | ### Map Props | Prop | Type | Required | Description | |------|------|----------|-------------| | id | string | No | Map container ID | | options | mapkit.MapConstructorOptions | No | Map configuration options | | location | Coordinate | No | Center Coordinate | | region | Region | No | Map region with center and span | | onMapError | (error: Error \| MapKitError) => void | No | Error handler | | onAppear | (map: mapkit.Map) => void | No | Called when map is ready | | onChange | (map: mapkit.Map, newAnnotations: mapkit.Annotation[]) => void | No | Called when annotations/overlays change | | className | string | No | Additional CSS classes | | loadingComponent | ReactNode | No | Custom loading component | | errorComponent | ReactNode | No | Custom error component | | onRegionChangeStart | (event: mapkit.EventBase) => void | No | Triggered when the map region starts changing. | | onRegionChangeEnd | (event: mapkit.EventBase) => void | No | Triggered when the map region finishes changing. | | onRotationStart | (event: mapkit.EventBase) => void | No | Triggered when the map starts rotating. | | onRotationEnd | (event: mapkit.EventBase) => void | No | Triggered when the map finishes rotating. | | onScrollStart | (event: mapkit.EventBase) => void | No | Triggered when the map starts scrolling. | | onScrollEnd | (event: mapkit.EventBase) => void | No | Triggered when the map finishes scrolling. | | onZoomStart | (event: mapkit.EventBase) => void | No | Triggered when the map starts zooming. | | onZoomEnd | (event: mapkit.EventBase) => void | No | Triggered when the map finishes zooming. | | onMapTypeChange | (event: mapkit.EventBase) => void | No | Triggered when the map type changes. | | onUserLocationChange | (event: mapkit.EventBase & { coordinate: mapkit.Coordinate; timestamp: Date }) => void | No | Triggered when the user's location changes. | | onUserLocationError | (event: mapkit.EventBase & { code: number; message: string }) => void | No | Triggered when an error occurs while trying to retrieve the user's location. | | onSingleTap | (event: mapkit.EventBase) => void | No | Triggered when the map is tapped once. | | onDoubleTap | (event: mapkit.EventBase) => void | No | Triggered when the map is double-tapped. | | onLongPress | (event: mapkit.EventBase) => void | No | Triggered when the map is long-pressed. | ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## License This project is licensed under the MIT License - see the LICENSE file for details.