Skip to main content

Overview

The PropertyMap component provides Google Maps integration for displaying property locations. The package includes two variants: a standard read-only map and a draggable version for location editing.

Import

import PropertyMap, { DraggablePropertyMap } from "../components/PropertyMap";

PropertyMap (Read-Only)

Standard map component for displaying a fixed property location.

Props

latitude
number
required
Latitude coordinate of the property location
longitude
number
required
Longitude coordinate of the property location
title
string
default:"Ubicación de la propiedad"
Title displayed on the map marker tooltip
className
string
default:""
Additional CSS classes to apply to the map container
height
string
default:"400px"
Height of the map container (CSS value)
zoom
number
default:15
Initial zoom level for the map (1-20)

Usage Examples

import PropertyMap from "../components/PropertyMap";

function PropertyDetail({ property }) {
  return (
    <section>
      <h2>Location</h2>
      <PropertyMap
        latitude={property.latitude}
        longitude={property.longitude}
        title={property.title}
      />
    </section>
  );
}

DraggablePropertyMap (Interactive)

Map component with a draggable marker for location editing in forms.

Props

Inherits all props from PropertyMap plus:
onLocationChange
(latitude: number, longitude: number) => void
Callback function triggered when the marker is dragged to a new position. Receives the new latitude and longitude.
draggable
boolean
default:true
Whether the marker can be dragged. Set to false for a read-only draggable map.

Usage Examples

import { DraggablePropertyMap } from "../components/PropertyMap";
import { useState } from "react";

function PropertyForm() {
  const [location, setLocation] = useState({
    latitude: -27.4516,
    longitude: -58.9858,
  });

  const handleLocationChange = (lat: number, lng: number) => {
    console.log("New location:", lat, lng);
    setLocation({ latitude: lat, longitude: lng });
  };

  return (
    <form>
      <label>Property Location</label>
      <p className="text-sm text-gray-600 mb-2">
        Drag the marker to set the exact location
      </p>
      
      <DraggablePropertyMap
        latitude={location.latitude}
        longitude={location.longitude}
        title="Drag to set location"
        height="400px"
        zoom={15}
        onLocationChange={handleLocationChange}
        draggable={true}
      />

      <input type="hidden" name="latitude" value={location.latitude} />
      <input type="hidden" name="longitude" value={location.longitude} />
    </form>
  );
}

Features

Automatic Map Initialization

Both components handle Google Maps API loading automatically:
  • Lazy loads the Google Maps JavaScript API
  • Uses @googlemaps/js-api-loader package
  • Caches the API instance for better performance
  • Includes Places library for additional features

Error Handling

Graceful error handling for missing data:
  • Displays fallback UI when coordinates are missing
  • Shows error message if API key is not configured
  • Console logging for debugging

Fallback UI

When coordinates are invalid or missing:
<div className="bg-gray-100 border border-gray-300 rounded-lg flex items-center justify-center">
  <div className="text-center text-gray-500">
    <div className="text-lg font-medium mb-2">
      Ubicación no disponible
    </div>
    <div className="text-sm">
      No se pudo cargar la ubicación de la propiedad
    </div>
  </div>
</div>

Marker Features

Read-Only Map

  • Fixed marker position
  • Marker title on hover
  • Automatic centering

Draggable Map

  • Draggable marker (when draggable={true})
  • dragend event triggers onLocationChange
  • Real-time coordinate updates

Map Controls

Both components configure the map with:
  • Disabled map type control
  • Disabled street view control
  • Enabled fullscreen control
  • Greedy gesture handling (no Ctrl+scroll requirement)

Configuration

Environment Variables

Both components require the Google Maps API key:
VITE_GOOGLE_MAPS_API_KEY=your_api_key_here

Google Maps API Setup

  1. Get an API key from Google Cloud Console
  2. Enable the following APIs:
    • Maps JavaScript API
    • Places API (optional, for future features)
  3. Set up billing (required by Google)
  4. Add the key to your .env file

Google Maps Loader

The components use a shared loader utility at src/lib/googleMaps.ts:1:
import { ensureGoogleMaps } from "../lib/googleMaps";

const google = await ensureGoogleMaps();
This utility:
  • Caches the Google Maps instance
  • Prevents multiple API loads
  • Returns a promise that resolves to the google object

Responsive Design

Both components are fully responsive:
  • Container uses provided height (default 400px)
  • Width automatically fills parent container
  • Touch-friendly on mobile devices
  • Gesture handling optimized for mobile

Accessibility

  • Map container has tabIndex={0} for keyboard focus
  • Descriptive aria-label attributes
  • DraggablePropertyMap includes drag instructions in label

Aria Labels

PropertyMap:
aria-label={`Mapa mostrando la ubicación de ${title}`}
DraggablePropertyMap:
aria-label={`Mapa interactivo mostrando la ubicación de ${title}. ${draggable ? "Arrastra el pin para ajustar la ubicación." : ""}`}

Lifecycle Management

Both components properly clean up resources:
  • Removes markers on unmount
  • Clears map instance references
  • Cancels pending API loads

TypeScript Types

The components define internal types for Google Maps objects:
type LatLngLiteral = { lat: number; lng: number };

interface GoogleMapInstance {
  setCenter: (latLng: LatLngLiteral) => void;
  setZoom: (zoom: number) => void;
}

interface GoogleMarkerInstance {
  setMap: (map: GoogleMapInstance | null) => void;
  setPosition: (latLng: LatLngLiteral) => void;
  addListener: (event: string, handler: () => void) => void;
}

Dependencies

  • @googlemaps/js-api-loader - Google Maps API loader
  • react - Hooks (useEffect, useRef)

Source Code

  • Standard map: src/components/PropertyMap.tsx:42
  • Draggable map: src/components/PropertyMap.tsx:141
  • Maps loader utility: src/lib/googleMaps.ts:1

Build docs developers (and LLMs) love