fahiem/filament-pinpoint

Google Maps location picker component for Filament 4 with search, draggable marker, and reverse geocoding

Installs: 224

Dependents: 0

Suggesters: 0

Security: 0

Stars: 9

Watchers: 2

Forks: 4

Open Issues: 1

Language:Blade

pkg:composer/fahiem/filament-pinpoint

v1.1.2 2025-12-19 03:57 UTC

This package is auto-updated.

Last update: 2025-12-19 04:10:15 UTC


README

Latest Version on Packagist Total Downloads License

📍 A Google Maps location picker component for Filament 4 with search, draggable marker, and reverse geocoding support.

Screenshot

Infolist View

Features

  • 🔍 Search location - Using Google Places Autocomplete
  • 📍 Click to set marker - Click anywhere on the map to place a marker
  • Draggable marker - Drag the marker to fine-tune the location
  • 📱 Current location - Get user's current device location
  • 🏠 Reverse geocoding - Auto-fill address fields from coordinates
  • 🌙 Dark mode support - Fully compatible with Filament's dark mode
  • 🌐 Multi-language support - Translations for EN, AR, NL, ID
  • ⚙️ Fully configurable - Customize height, zoom, default location, and more

Requirements

  • PHP 8.1+
  • Laravel 10+ / 11+ / 12+
  • Filament 4.0+
  • Google Maps API Key with the following APIs enabled:
    • Maps JavaScript API
    • Places API
    • Geocoding API

Installation

Install the package via Composer:

composer require fahiem/filament-pinpoint

Configuration

1. Set your Google Maps API Key

Add your Google Maps API key to your .env file:

GOOGLE_MAPS_API_KEY=your_api_key_here

2. Publish the config file (optional)

php artisan vendor:publish --tag="filament-pinpoint-config"

This will publish the config file to config/filament-pinpoint.php:

return [
    'api_key' => env('GOOGLE_MAPS_API_KEY'),

    'default' => [
        'lat' => env('GOOGLE_MAPS_DEFAULT_LAT', -0.5050),
        'lng' => env('GOOGLE_MAPS_DEFAULT_LNG', 117.1500),
        'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 13),
        'height' => env('GOOGLE_MAPS_DEFAULT_HEIGHT', 400),
    ],
];

You can also set default values via environment variables:

GOOGLE_MAPS_API_KEY=your_api_key_here
GOOGLE_MAPS_DEFAULT_LAT=-6.200000
GOOGLE_MAPS_DEFAULT_LNG=106.816666
GOOGLE_MAPS_DEFAULT_ZOOM=15
GOOGLE_MAPS_DEFAULT_HEIGHT=500

Usage

Basic Usage

use Fahiem\FilamentPinpoint\Pinpoint;

public static function form(Form $form): Form
{
    return $form
        ->schema([
            Pinpoint::make('location')
                ->label('Location')
                ->latField('lat')
                ->lngField('lng'),

            TextInput::make('lat')
                ->label('Latitude')
                ->readOnly(),

            TextInput::make('lng')
                ->label('Longitude')
                ->readOnly(),
        ]);
}

Full Example with All Options

use Fahiem\FilamentPinpoint\Pinpoint;

Pinpoint::make('location')
    ->label('Business Location')
    ->defaultLocation(-6.200000, 106.816666) // Jakarta
    ->defaultZoom(15)
    ->height(400)
    ->draggable()
    ->searchable()
    ->latField('lat')
    ->lngField('lng')
    ->addressField('address')            // Auto-fill address field
    ->shortAddressField('short_address') // Auto-fill short address field (exclude province, city, district, village, and postal code)
    ->provinceField('province')          // Auto-fill province field
    ->cityField('city')                  // Auto-fill city/county field
    ->districtField('district')          // Auto-fill district field
    ->villageField('village')            // Auto-fill village/district field
    ->postalCodeField('postal_code')     // Auto-fill postal/zip code field
    ->countryField('country')            // Auto-fill country field
    ->columnSpanFull()

Disable Features

Pinpoint::make('location')
    ->draggable(false)  // Disable marker dragging
    ->searchable(false) // Hide search box

Using with Repeater

Pinpoint fully supports Filament's Repeater component. Each repeater item gets its own independent map and fields:

use Fahiem\FilamentPinpoint\Pinpoint;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;

Repeater::make('branches')
    ->schema([
        TextInput::make('branch_name')
            ->label('Branch Name')
            ->required(),

        Pinpoint::make('location')
            ->label('Location')
            ->latField('latitude')
            ->lngField('longitude')
            ->addressField('address')
            ->draggable()
            ->searchable()
            ->height(300),

        TextInput::make('latitude')
            ->label('Latitude')
            ->readOnly(),

        TextInput::make('longitude')
            ->label('Longitude')
            ->readOnly(),

        TextInput::make('address')
            ->label('Address')
            ->readOnly()
            ->columnSpanFull(),
    ])
    ->columns(2)
    ->columnSpanFull()

Note: When using with Repeater, the field paths are automatically calculated (e.g., data.branches.0.latitude for the first item).

Infolist Entry (Read-Only Display)

For displaying locations in infolists (view mode), use the PinpointEntry component. It displays a clean, read-only Google Map with a marker at the specified coordinates.

use Fahiem\FilamentPinpoint\PinpointEntry;

public static function infolist(Infolist $infolist): Infolist
{
    return $infolist
        ->schema([
            PinpointEntry::make('location')
                ->label('Location')
                ->latField('lat')
                ->lngField('lng')
                ->columnSpanFull(),
        ]);
}

Customization Options

PinpointEntry::make('location')
    ->label('Business Location')
    ->defaultLocation(-6.200000, 106.816666) // Jakarta
    ->defaultZoom(15)
    ->height(400)
    ->latField('lat')
    ->lngField('lng')
    ->columnSpanFull()

The PinpointEntry displays:

  • A read-only Google Map with a marker at the specified coordinates
  • No text or address information - just a clean map view
  • Full dark mode support

Available Methods

Pinpoint (Form Field)

Method Description Default
defaultLocation(float $lat, float $lng) Set default center location -0.5050, 117.1500
defaultZoom(int $zoom) Set default zoom level 13
height(int $height) Set map height in pixels 400
latField(string $field) Field name for latitude 'lat'
lngField(string $field) Field name for longitude 'lng'
addressField(string $field) Field name for auto-fill address null
shortAddressField(string $field) Field name for auto-fill short address null
provinceField(string $field) Field name for auto-fill province null
cityField(string $field) Field name for auto-fill city/county null
districtField(string $field) Field name for auto-fill district null
villageField(string $field) Field name for auto-fill village/sub-district null
postalCodeField(string $field) Field name for auto-fill postal/zip code null
countryField(string $field) Field name for auto-fill country null
draggable(bool $draggable) Enable/disable marker dragging true
searchable(bool $searchable) Enable/disable search box true

PinpointEntry (Infolist Entry)

Method Description Default
defaultLocation(float $lat, float $lng) Set default center location -0.5050, 117.1500
defaultZoom(int $zoom) Set default zoom level 13
height(int $height) Set map height in pixels 400
latField(string $field) Field name for latitude 'lat'
lngField(string $field) Field name for longitude 'lng'
getLat() Get latitude from record Returns field value or default
getLng() Get longitude from record Returns field value or default

Getting a Google Maps API Key

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Enable the following APIs:
    • Maps JavaScript API
    • Places API
    • Geocoding API
  4. Go to Credentials and create an API key
  5. (Recommended) Restrict your API key to specific domains

Database Migration

Make sure your table has columns for latitude and longitude:

Schema::create('locations', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->decimal('lat', 10, 7)->nullable();
    $table->decimal('lng', 10, 7)->nullable();
    $table->text('address')->nullable();
    $table->text('short_address')->nullable();
    $table->string('province')->nullable();
    $table->string('city')->nullable();
    $table->string('district')->nullable();
    $table->string('village')->nullable();
    $table->string('postal_code')->nullable();
    $table->string('country')->nullable();
    $table->timestamps();
});

Translations

This package supports multiple languages out of the box:

Language Code
English en
Arabic ar
Dutch nl
Indonesian id

Publishing Translations

To customize the translations, publish them to your application:

php artisan vendor:publish --tag="filament-pinpoint-translations"

This will publish the translation files to lang/vendor/filament-pinpoint/.

Adding New Languages

Create a new folder in lang/vendor/filament-pinpoint/{locale}/ with a pinpoint.php file:

<?php

return [
    'search' => 'Your translation...',
    'use_my_location' => 'Your translation...',
    'instructions' => 'Your translation...',
    'loading_map' => 'Your translation...',
];

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security-related issues, please email amfahiem010502@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.