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
Requires
- php: ^8.1
- filament/filament: ^4.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- orchestra/testbench: ^9.0
- pestphp/pest: ^2.0
README
📍 A Google Maps location picker component for Filament 4 with search, draggable marker, and reverse geocoding support.
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.latitudefor 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
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the following APIs:
- Maps JavaScript API
- Places API
- Geocoding API
- Go to Credentials and create an API key
- (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.

