PHPackages                             darkclow4/filament-map-picker - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. darkclow4/filament-map-picker

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

darkclow4/filament-map-picker
=============================

Leaflet map picker and GeoJSON draw field for Filament 5.

v5.0.0(1mo ago)22↓100%MITJavaScriptPHP ^8.3CI failing

Since May 7Pushed 1mo agoCompare

[ Source](https://github.com/darkclow4/filament-map-picker)[ Packagist](https://packagist.org/packages/darkclow4/filament-map-picker)[ Docs](https://github.com/darkclow4/filament-map-picker)[ RSS](/packages/darkclow4-filament-map-picker/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

Filament Map Picker
===================

[](#filament-map-picker)

`filament-map-picker` is a custom field for Filament 5 that provides an interactive Leaflet.js map for selecting a point location and, optionally, drawing one or more map areas as GeoJSON.

The package is designed to stay flexible. It does not force how you persist `latitude`, `longitude`, or area data. Instead, it keeps a predictable field state and lets you map the values however you want through `afterStateUpdated()` and `afterStateHydrated()`.

Features
--------

[](#features)

- Built for Filament 5
- Powered by locally bundled Leaflet.js and Leaflet Draw
- Default OpenStreetMap tile layer
- Custom tile support through `->tiles([...])`
- `drag` mode and `click` mode for the point marker
- Optional geocoding search UI
- Optional polygon, rectangle, and circle drawing tools
- Optional multi-shape GeoJSON collections
- Combined point + area state in a single field
- Reactive Livewire-friendly state updates
- Alpine.js powered interaction
- Leaflet layers control for switching tile layers

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 13+
- Filament 5

Installation
------------

[](#installation)

Install the package with Composer:

```
composer require darkclow4/filament-map-picker
```

Then publish Filament assets:

```
php artisan filament:assets
```

Package Registration
--------------------

[](#package-registration)

The package supports Laravel auto-discovery through:

```
Darkclow4\FilamentMapPicker\FilamentMapPickerServiceProvider::class
```

In most applications, no manual provider registration is needed.

State Format
------------

[](#state-format)

### Point-only mode

[](#point-only-mode)

By default, the field stores point coordinates as:

```
[
    'lat' => -6.2,
    'lng' => 106.816666,
]
```

### Point + draw mode

[](#point--draw-mode)

When draw mode is enabled, the field stores a combined state:

```
[
    'lat' => -6.2,
    'lng' => 106.816666,
    'geojson' => [
        'type' => 'FeatureCollection',
        'features' => [
            // polygon / rectangle / circle features
        ],
    ],
]
```

This makes it easy to keep a marker location and one or more service-area shapes in the same field while still saving them into separate database columns.

Basic Usage
-----------

[](#basic-usage)

### Point-only field

[](#point-only-field)

```
use Darkclow4\FilamentMapPicker\Forms\Components\MapPicker;
use Filament\Schemas\Components\Utilities\Set;

MapPicker::make('location')
    ->mode('click')
    ->defaultLocation(-6.2, 106.816666)
    ->zoom(13)
    ->height(420)
    ->live()
    ->afterStateUpdated(function (?array $state, Set $set): void {
        $set('latitude', $state['lat'] ?? null);
        $set('longitude', $state['lng'] ?? null);
    });
```

### Point + area in a single field

[](#point--area-in-a-single-field)

```
use Darkclow4\FilamentMapPicker\Forms\Components\MapPicker;
use Filament\Forms\Components\Hidden;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;

MapPicker::make('location')
    ->mode('drag')
    ->defaultLocation(-6.2, 106.816666)
    ->drawable()
    ->drawTools(['polygon', 'rectangle', 'circle'])
    ->multipleShapes()
    ->fitDrawBounds(false)
    ->height(480)
    ->live()
    ->afterStateHydrated(function (MapPicker $component, Get $get): void {
        $component->state([
            'lat' => is_numeric($get('latitude')) ? (float) $get('latitude') : -6.2,
            'lng' => is_numeric($get('longitude')) ? (float) $get('longitude') : 106.816666,
            'geojson' => is_array($get('area'))
                ? $get('area')
                : [
                    'type' => 'FeatureCollection',
                    'features' => [],
                ],
        ]);
    })
    ->afterStateUpdated(function (?array $state, Set $set): void {
        $set('latitude', $state['lat'] ?? null);
        $set('longitude', $state['lng'] ?? null);
        $set('area', $state['geojson'] ?? [
            'type' => 'FeatureCollection',
            'features' => [],
        ]);
    });

Hidden::make('area');
```

Selection Modes
---------------

[](#selection-modes)

### Drag mode

[](#drag-mode)

```
MapPicker::make('location')->mode('drag')
```

- the user drags the map
- the marker stays centered
- coordinates are taken from the map center

### Click mode

[](#click-mode)

```
MapPicker::make('location')->mode('click')
```

- the user clicks on the map
- the marker moves to the clicked point
- coordinates are taken from that point

Default Tile Layer
------------------

[](#default-tile-layer)

If you do not provide custom tiles, the field uses OpenStreetMap automatically.

```
MapPicker::make('location')
    ->tile('osm')
```

Built-in default tile definition:

```
[
    'osm' => [
        'label' => 'OpenStreetMap',
        'url' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        'options' => [
            'maxZoom' => 19,
            'attribution' => '&copy; OpenStreetMap contributors',
        ],
    ],
]
```

Custom Tile Layers
------------------

[](#custom-tile-layers)

You can provide your own tile layers with `->tiles([...])`. Those definitions are serialized to JSON and passed directly to Leaflet.

```
MapPicker::make('location')
    ->tiles([
        'opentopo' => [
            'label' => 'Open Topo Map',
            'url' => 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
            'options' => [
                'maxZoom' => 19,
                'attribution' => 'Map data: &copy; OpenStreetMap contributors | Map style: &copy; OpenTopoMap',
            ],
        ],
    ])
    ->tile('opentopo');
```

Tile behavior:

- if `->tiles()` is not called, only `osm` is available
- if `->tile()` is not called, `osm` is selected by default
- if the selected tile key is invalid, the field falls back to `osm`
- if more than one base layer exists, Leaflet's built-in layers control is shown on the map
- by default the built-in `osm` tile is always included
- use `->showDefaultTile(false)` if you want to hide the built-in `osm` tile and only expose your custom tiles

Searchable Mode
---------------

[](#searchable-mode)

Enable geocoding search when you want users to jump quickly to a location:

```
MapPicker::make('location')
    ->searchable()
    ->searchPlaceholder('Search for a place')
    ->searchResultLimit(8)
```

Behavior:

- users can search for a place or address
- matching results appear in a dropdown list
- selecting a result recenters the map and updates the field state
- selected results are highlighted when reopened

By default, search uses:

```
https://nominatim.openstreetmap.org/search
```

You can override it:

```
->searchProviderUrl('https://nominatim.openstreetmap.org/search')
```

Drawing Shapes as GeoJSON
-------------------------

[](#drawing-shapes-as-geojson)

Enable draw mode when you want the user to define areas while keeping a marker location in the same field state.

```
MapPicker::make('location')
    ->drawable()
    ->drawTools(['polygon', 'rectangle', 'circle'])
    ->multipleShapes()
    ->fitDrawBounds(false)
```

Notes:

- draw mode stores the field state as `['lat', 'lng', 'geojson']`
- the marker location still works as normal
- the drawn area is stored inside `geojson`
- by default only one drawn shape is kept at a time
- use `->multipleShapes()` if you want multiple polygons / rectangles / circles in the same `FeatureCollection`
- editing or deleting shapes updates the field state automatically
- use `afterStateUpdated()` / `afterStateHydrated()` to map `latitude`, `longitude`, and `geojson` into separate database columns

API Reference
-------------

[](#api-reference)

### `->tile(string $tile)`

[](#-tilestring-tile)

Sets the active tile key.

```
->tile('osm')
```

### `->tiles(array $tiles)`

[](#-tilesarray-tiles)

Registers custom tile layers.

Expected tile format:

```
[
    'custom-key' => [
        'label' => 'Tile Name',
        'url' => 'https://example.com/{z}/{x}/{y}.png',
        'options' => [
            'maxZoom' => 20,
            'attribution' => '...'
        ],
    ],
]
```

### `->showDefaultTile(bool $condition = true)`

[](#-showdefaulttilebool-condition--true)

Controls whether the built-in `osm` tile should be included in the available tile list.

```
->showDefaultTile(false)
```

### `->mode('drag|click')`

[](#-modedragclick)

Defines the point marker interaction mode.

```
->mode('drag')
->mode('click')
```

### `->defaultLocation(float $lat, float $lng)`

[](#-defaultlocationfloat-lat-float-lng)

Sets the initial map coordinates.

```
->defaultLocation(-6.2, 106.816666)
```

### `->zoom(int $level)`

[](#-zoomint-level)

Sets the initial map zoom level.

```
->zoom(13)
```

### `->height(int|string $height)`

[](#-heightintstring-height)

Sets the map container height.

```
->height(420)
->height('32rem')
->height('60vh')
```

### `->markerColor(string $color)`

[](#-markercolorstring-color)

Sets the marker color used in both `drag` and `click` modes.

```
->markerColor('#0f766e')
->markerColor('rgb(37, 99, 235)')
```

### `->searchable(bool $condition = true)`

[](#-searchablebool-condition--true)

Enables place search.

```
->searchable()
```

### `->searchPlaceholder(string $placeholder)`

[](#-searchplaceholderstring-placeholder)

Overrides the search input placeholder.

```
->searchPlaceholder('Search for a city or address')
```

### `->searchProviderUrl(string $url)`

[](#-searchproviderurlstring-url)

Overrides the geocoding endpoint used by the search box.

```
->searchProviderUrl('https://nominatim.openstreetmap.org/search')
```

### `->searchResultLimit(int $limit)`

[](#-searchresultlimitint-limit)

Controls how many search results are shown in the dropdown.

```
->searchResultLimit(8)
```

### `->drawable(bool $condition = true)`

[](#-drawablebool-condition--true)

Enables shape drawing tools and switches the field state into combined point + GeoJSON mode.

```
->drawable()
```

### `->drawTools(array $tools)`

[](#-drawtoolsarray-tools)

Controls which draw tools are available. Supported values are `polygon`, `rectangle`, and `circle`.

```
->drawTools(['polygon', 'rectangle'])
```

### `->fitDrawBounds(bool $condition = true)`

[](#-fitdrawboundsbool-condition--true)

Controls whether the map should automatically fit to the drawn shapes after create or edit.

```
->fitDrawBounds(false)
```

### `->multipleShapes(bool $condition = true)`

[](#-multipleshapesbool-condition--true)

Allows the field to keep multiple drawn shapes inside the GeoJSON `FeatureCollection`.

```
->multipleShapes()
```

### `->showAreaMeasurement(bool $condition = true)`

[](#-showareameasurementbool-condition--true)

Shows area labels directly inside the map for each drawn shape when draw mode is enabled.

```
->showAreaMeasurement()
```

### `->areaMeasurementUnit('m2'|'ha')`

[](#-areameasurementunitm2ha)

Controls the unit used for the displayed area measurement.

```
->areaMeasurementUnit('m2')
->areaMeasurementUnit('ha')
```

Notes
-----

[](#notes)

- The package does not force any persistence strategy for `latitude`, `longitude`, or area GeoJSON
- You are free to map the field state into any schema structure you prefer
- Custom tiles are the developer's responsibility, including availability and usage terms
- Search providers are the developer's responsibility, including availability and usage terms

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance93

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

34d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/54412655?v=4)[Muhammad Irfan Muttaqin](/maintainers/darkclow4)[@darkclow4](https://github.com/darkclow4)

---

Top Contributors

[![darkclow4](https://avatars.githubusercontent.com/u/54412655?v=4)](https://github.com/darkclow4 "darkclow4 (10 commits)")

---

Tags

laravelmapsleafletfilamentfilament-plugingeojsonmap-pickerfilament-form-fieldleaflet-draw

### Embed Badge

![Health badge](/badges/darkclow4-filament-map-picker/health.svg)

```
[![Health](https://phpackages.com/badges/darkclow4-filament-map-picker/health.svg)](https://phpackages.com/packages/darkclow4-filament-map-picker)
```

###  Alternatives

[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3913.7k](/packages/rawilk-profile-filament-plugin)[dotswan/filament-map-picker

Easily pick and retrieve geo-coordinates using a map-based interface in your Filament applications.

127173.7k3](/packages/dotswan-filament-map-picker)[codewithdennis/filament-select-tree

The multi-level select field enables you to make single selections from a predefined list of options that are organized into multiple levels or depths.

327482.0k25](/packages/codewithdennis-filament-select-tree)[croustibat/filament-jobs-monitor

Background Jobs monitoring like Horizon for all drivers for FilamentPHP

264298.4k8](/packages/croustibat-filament-jobs-monitor)[stephenjude/filament-jetstream

A Laravel starter kit built with Filament inspired by Jetstream.

17758.9k2](/packages/stephenjude-filament-jetstream)[creagia/filament-code-field

A Filamentphp input field to edit or view code data.

57301.3k3](/packages/creagia-filament-code-field)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
