lbcdev/livewire-map-component
Componente Livewire para mapas interactivos con Leaflet.js: marcadores arrastrables, clic en el mapa para colocar puntos, entrada manual de coordenadas, modo claro/oscuro y solo lectura, y eventos Livewire. Ideal para formularios de ubicación en Laravel.
Display a draggable marker:
<livewire:lbcdev-map
latitude="40.7128"
longitude="-74.0060"
:markers="['40.7128,-74.0060']"
marker-draggable="true"
/>
Requires v1.0.5+ if the map sits underneath modals/dropdowns in your host app — see Gotchas.
Dynamic Marker Management:
// In Livewire component
public $markers = ['40.7128,-74.0060', '34.0522,-118.2437'];
public function addMarker($lat, $lng) {
$this->markers[] = "$lat,$lng";
}
<livewire:lbcdev-map
:markers="$markers"
@marker-added="addMarker"
/>
Event-Driven Integration:
@map-clicked="handleMapClick($event)"@marker-dragged="updateMarker($event)"public function handleMapClick($event) {
$this->addMarker($event['lat'], $event['lng']);
}
Theme Switching:
<livewire:lbcdev-map
:darkMode="app()->isDarkModeEnabled()"
/>
Inside Modals / Slide-overs:
Since v1.0.5 the map root uses a CSS isolation: isolate stacking context, so it no longer paints over host-app modals. If a map is the modal body, keep the modal content scrollable with a fixed map height (class="h-64" or a wrapper with height), otherwise Leaflet renders 0px tall inside a collapsed container. Call map.invalidateSize() after the modal opens if tiles look off-center.
Form Submission: Bind marker data to a model:
public $location;
public function updatedMarkers() {
$this->location = implode(',', $this->markers);
}
<input wire:model="location" type="hidden">
Custom Styling:
Publish views (php artisan vendor:publish --tag=lbcdev-map-views) and override:
@push('leaflet-styles')
.leaflet-container { border-radius: 8px; }
@endpush
Server-Side Validation:
protected $rules = [
'markers' => 'required|array',
'markers.*' => 'regex:/^\d+\.\d+,\s*-\d+\.\d+$/'
];
Missing Leaflet Dependencies:
@livewireStyles.Marker Coordinates Format:
markers prop expects strings like "40.7128,-74.0060" (not arrays/objects).implode(',', [$lat, $lng]) when passing PHP arrays.Event Payload Mismatch:
@marker-dragged emits {lat, lng, id}, but your handler expects {lat, lng}.public function updateMarker($event) {
$this->markers[$event['id']] = "$event['lat'],$event['lng']";
}
Read-Only Mode Quirks:
Stacking Context / Overlay Overlap (v1.0.5):
isolation: isolate, creating its own stacking context. Leaflet's internal panes/controls (z-index 400–1000) no longer escape and cover your app's modals, dropdowns, toasts, or sticky headers.z-index: 9999 on modal wrappers, z-index: 0 on the map, !important overrides). They are no longer needed and can now fight the new isolation context.vendor:publish --tag=lbcdev-map-views --force) so your published copy contains the isolation rule; stale published views keep the old bug. Then php artisan view:clear.Inspect Events:
@this.on('marker-dragged', function(event) {
console.log('Event:', event);
})
Overlay Still Covered?:
Check the computed z-index of the map's ancestors — a parent with transform, filter, opacity < 1, or its own z-index creates a new stacking context and re-introduces the problem regardless of the package fix. Move the map wrapper out of such a parent or raise the modal's stacking context.
Check Published Views:
If customizations disappear after vendor:publish, clear cached views:
php artisan view:clear
Custom Layers:
Override the mountMap method in your Livewire component:
public function mountMap() {
$this->map->addLayer(LbcdevMap::tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'));
}
Geocoding:
Integrate with a service (e.g., Nominatim) via @map-clicked:
public function handleMapClick($event) {
$address = $this->geocode($event['lat'], $event['lng']);
$this->address = $address;
}
Performance:
marker-cluster-group:
public function mountMap() {
$this->map->addLayer(LbcdevMap::markerClusterGroup($this->markers));
}
@map-view event.invalidateSize() on open instead of re-rendering.How can I help you explore Laravel packages today?