PHPackages                             kwasii/livewire-mapcn - 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. kwasii/livewire-mapcn

ActiveLibrary

kwasii/livewire-mapcn
=====================

Mapcn inspired laravel livewire package to add maps to your laravel livewire project

v1.0.4(2mo ago)494[1 PRs](https://github.com/kwasii1/livewire-mapcn/pulls)MITJavaScriptPHP ^8.4CI passing

Since Feb 25Pushed 1mo agoCompare

[ Source](https://github.com/kwasii1/livewire-mapcn)[ Packagist](https://packagist.org/packages/kwasii/livewire-mapcn)[ Docs](https://github.com/kwasii/livewire-mapcn)[ GitHub Sponsors](https://github.com/kwasii)[ RSS](/packages/kwasii-livewire-mapcn/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (26)Versions (10)Used By (0)

Livewire Mapcn
==============

[](#livewire-mapcn)

A Laravel Livewire package inspired by [mapcn.dev](https://mapcn.dev). Easily integrate beautiful, interactive maps into your Laravel applications using MapLibre GL JS, Tailwind CSS, and Alpine.js.

---

Getting Started
---------------

[](#getting-started)

`livewire-mapcn` provides a set of Blade components that wrap MapLibre GL JS functionality in a "Livewire-friendly" way. It supports common mapping features like markers, popups, routes, route groups, route lists, and clustering, all while being responsive and theme-aware.

### Core Concepts

[](#core-concepts)

- **Declarative Maps**: Define your map and its features using expressive Blade tags.
- **Livewire Integration**: Interact with the map from your PHP component via events.
- **Theme Support**: Built-in support for light, dark, and auto themes (following Tailwind's `.dark` class).
- **Extensibility**: Custom providers, MapLibre style JSON support, and custom event forwarding.

---

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

[](#installation)

### 1. Install via Composer

[](#1-install-via-composer)

```
composer require kwasii/livewire-mapcn
```

### 2. Publish Configuration and Assets

[](#2-publish-configuration-and-assets)

```
php artisan vendor:publish --tag="livewire-mapcn-config"
php artisan vendor:publish --tag="livewire-mapcn-assets"
```

### 3. Setup Layout

[](#3-setup-layout)

Include the styles and scripts in your root layout (e.g., `app.blade.php`).

```

    @livewireMapStyles

    @livewireScripts
    @livewireMapScripts

```

> Ensure you have Alpine.js and Tailwind CSS installed in your project, as they are required for this package to function correctly.

---

Configuration
-------------

[](#configuration)

You can customize the package behavior via `config/livewire-mapcn.php`.

KeyDefaultDescription`default_provider``'carto-positron'`Default tile provider for all maps.`dark_provider``'carto-dark-matter'`Provider used for dark mode.`default_height``'full'`Default CSS height if not specified in prop.`default_zoom``7`Default initial zoom level.`default_center``[0, 0]`Default initial coordinates `[lng, lat]`.`osrm_url``'https://router.project-osrm.org'`Base URL for fetching road directions via OSRM.`inject_assets``'route'``'route'` (auto-load via Laravel routes) or `'published'` (manual).`load_from_cdn``true`Load MapLibre JS/CSS from CDN or local.`maplibre_version``'5.19.0'`MapLibre GL JS version used for CDN fallback.`cdn_url``'https://cdn.jsdelivr.net/npm/maplibre-gl@4.x/dist/maplibre-gl.js'`CDN URL for MapLibre GL JS.`cdn_css_url``'https://cdn.jsdelivr.net/npm/maplibre-gl@4.x/dist/maplibre-gl.css'`CDN URL for MapLibre GL CSS.`carto_license``'non-commercial'`CARTO basemap license type (`'non-commercial'` or `'enterprise'`).`cluster_popup_view``null`Optional Blade view for cluster point popups.`custom_events``[]`Array of custom MapLibre event names to forward (dispatched as `map:*`).---

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

[](#api-reference)

The package provides several Blade components. All components must be nested inside the root `` component.

### Table of Contents

[](#table-of-contents)

- [Map (``)](#map-x-map)
- [Controls (``)](#controls-x-map-controls)
- [Markers (``)](#markers-x-map-marker)
- [Popups (``)](#popups-x-map-popup)
- [Routes (``)](#routes-x-map-route)
- [Route Groups (``)](#route-groups-x-map-route-group)
- [Route List (``)](#route-list-x-map-route-list)
- [Clusters (``)](#clusters-x-map-cluster-layer)
- [Advanced Usage](#advanced-usage)

---

Map (``)
---------------

[](#map-x-map)

The base component for any map implementation.

### Usage

[](#usage)

```

```

### Props

[](#props)

PropTypeDefaultDescription`:center``array``[0, 0]`Initial map center `[lng, lat]`.`:zoom``int``13`Initial zoom level (0–22).`:min-zoom``int``0`Minimum zoom level.`:max-zoom``int``22`Maximum zoom level.`provider``string``'carto-voyager'`Options: `carto-voyager`, `carto-positron`, `carto-dark-matter`, `osm-raster`, `custom`.`style``string``null`Custom MapLibre style JSON URL (overrides `provider`).`theme``string``'auto'``'light'`, `'dark'`, or `'auto'` (follows `.dark` class).`height``string``'full'`CSS height (e.g., `500px`, `100vh`, `full`).`width``string``'100%'`CSS width.`:bearing``float``0`Initial bearing in degrees.`:pitch``float``0`Initial pitch (0–60 degrees).`:interactive``bool``true`Enable mouse/touch interactions.`:scroll-zoom``bool``true`Allow mouse wheel zoom.`:double-click-zoom``bool``true`Allow double-click zoom.`:drag-pan``bool``true`Allow panning by drag.`class``string``''`Additional CSS classes for the map container.`light-style``string``null`Custom MapLibre style JSON URL for light mode.`dark-style``string``null`Custom MapLibre style JSON URL for dark mode.`:events``array``[]`Array of custom MapLibre event names to forward (merged with config `custom_events`).---

Controls (``)
-----------------------------

[](#controls-x-map-controls)

Adds standard interactive controls to the map.

### Usage

[](#usage-1)

```

```

### Props

[](#props-1)

PropTypeDefaultDescription`:zoom``bool``true`Show zoom in/out buttons.`:compass``bool``true`Show compass/bearing reset.`:locate``bool``true`Show geolocation button.`:fullscreen``bool``false`Show fullscreen toggle.`:scale``bool``false`Show map scale bar.`position``string``'top-right'`Position: `top-right`, `top-left`, `bottom-right`, `bottom-left`.`class``string``''`Additional CSS classes.---

Markers (``)
--------------------------

[](#markers-x-map-marker)

Display interactive markers on the map.

### Usage

[](#usage-2)

```

            Our HQ
            Visit us anytime!

```

### Custom Marker Content

[](#custom-marker-content)

```

            ...

```

### Props

[](#props-2)

PropTypeDefaultDescription`:lat``float`**Required**Latitude.`:lng``float`**Required**Longitude.`id``string`UUIDUnique marker identifier.`:draggable``bool``false`Allow user to drag marker.`color``string``'#1A56DB'`Default dot color.`anchor``string``'bottom'`Anchor point (`center`, `bottom`, `top`, `left`, `right`, etc.).`:offset``array``[0, 0]`Pixel offset `[x, y]` from anchor position.`:rotation``float``0`Rotation angle in degrees.`rotation-alignment``string``'auto'`Rotation alignment (`'auto'`, `'map'`, `'viewport'`).`pitch-alignment``string``'auto'`Pitch alignment (`'auto'`, `'map'`, `'viewport'`).`class``string``''`Additional CSS classes.### Marker Sub-Components

[](#marker-sub-components)

Markers can be customized using these child components:

#### ``

[](#x-marker-content)

Renders custom HTML as the marker icon.

PropTypeDefaultDescription`class``string``''`Additional CSS classes.```

```

#### ``

[](#x-marker-label)

Adds a text label near the marker. Styled with a frosted glass effect, subtle border, and automatic dark mode support.

PropTypeDefaultDescription`text``string`**Required**The label text.`position``string``'bottom'`Position: `top`, `bottom`, `left`, `right`.`class``string``''`Additional CSS classes.#### ``

[](#x-marker-tooltip)

Adds a hover tooltip using MapLibre's Popup. Styled with a dark pill in light mode and a light pill in dark mode for maximum contrast.

PropTypeDefaultDescription`text``string`**Required**The tooltip text.`anchor``string``'top'`Tooltip anchor position.`:offset``array``[0, -10]`Pixel offset `[x, y]` from anchor.`class``string``''`Additional CSS classes.#### ``

[](#x-marker-popup)

Adds a click-to-open popup.

PropTypeDefaultDescription`max-width``string``'300px'`CSS max-width for the popup.`:close-button``bool``true`Show close (×) button.`:close-on-click-map``bool``true`Close popup when clicking the map.`:close-on-move``bool``false`Close popup when the map moves.`anchor``string``'bottom'`Where to anchor relative to marker.`:offset``array``[0, 0]`Pixel offset `[x, y]` from anchor.`class``string``''`Additional CSS classes.---

Popups (``)
------------------------

[](#popups-x-map-popup)

Standalone popups anchored to specific coordinates.

### Usage

[](#usage-3)

```

        This is a standalone popup.

```

### Props

[](#props-3)

PropTypeDefaultDescription`:lat``float`**Required**Latitude.`:lng``float`**Required**Longitude.`id``string`UUIDUnique popup identifier.`:open``bool``true`Initial visibility.`max-width``string``'300px'`CSS max-width.`:close-button``bool``false`Show close icon.`:close-on-click-map``bool``true`Close popup when clicking the map.`:close-on-move``bool``false`Close when the map moves.`anchor``string``'bottom'`Anchor position relative to coordinates.`:offset``array``[0, 0]`Pixel offset `[x, y]` from anchor.`class``string``''`Additional CSS classes.---

Routes (``)
------------------------

[](#routes-x-map-route)

Draw polylines or fetch real driving/walking/cycling directions.

### Basic Polyline

[](#basic-polyline)

```

```

### Styled Route

[](#styled-route)

```

```

### OSRM Directions with Alternatives

[](#osrm-directions-with-alternatives)

```

```

### Interactive Route

[](#interactive-route)

```

```

### Props

[](#props-4)

PropTypeDefaultDescription`:coordinates``array`**Required**Array of `[lng, lat]` pairs.`id``string`UUIDUnique route identifier.`color``string``'#1A56DB'`Line color.`:width``int``4`Line width in pixels.`:opacity``float``1.0`Line opacity (0–1).`:dash-array``array``null`Dash pattern array (e.g., `[5, 3]` for dashed lines).`line-cap``string``'round'`Line cap style (`'butt'`, `'round'`, `'square'`).`line-join``string``'round'`Line join style (`'bevel'`, `'round'`, `'miter'`).`active-color``string``'#0F43C4'`Color when the route is active/selected.`:active-width``int``6`Width when the route is active/selected.`hover-color``string``null`Color on mouse hover.`:clickable``bool``true`Whether the route responds to click events.`:with-stops``bool``false`Show markers at each coordinate.`stop-color``string``'#1A56DB'`Color of stop markers when `:with-stops` is true.`:fetch-directions``bool``false`Fetch road geometry from OSRM.`directions-profile``string``'driving'`OSRM profile: `driving`, `walking`, `cycling`.`directions-url``string`config `osrm_url`Custom OSRM base URL (overrides config).`:animate``bool``false`Animate drawn route.`:animate-duration``int``2000`Animation duration in milliseconds.`:active``bool``false`Whether the route starts in active state.`:alternatives``bool``true`Fetch and display alternative routes from OSRM.`:max-alternatives``int``2`Maximum number of alternative routes to show.`alternative-color``string``'#94A3B8'`Color of alternative route lines.`:alternative-opacity``float``0.5`Opacity of alternative route lines.`:alternative-width``int``3`Width of alternative route lines.### Dynamic Route Updates

[](#dynamic-route-updates)

Update a route's coordinates without a full re-render:

```
// In your Livewire component
$this->dispatch("map:update-route-data-{$routeId}", [
    'coordinates' => $newCoordinates,
]);
```

---

Route Groups (``)
------------------------------------

[](#route-groups-x-map-route-group)

Render multiple pre-defined routes with click-to-select behavior. Useful for showing several itineraries on the same map.

### Usage

[](#usage-4)

```
// In your Livewire component
public array $routes = [
    [
        'id' => 'route-a',
        'coordinates' => [[-0.12, 51.51], [-0.11, 51.51], [-0.10, 51.50]],
        'color' => '#ef4444',
        'width' => 4,
    ],
    [
        'id' => 'route-b',
        'coordinates' => [[-0.12, 51.51], [-0.115, 51.515], [-0.10, 51.50]],
        'color' => '#3b82f6',
        'width' => 4,
    ],
];
```

```

```

### Props

[](#props-5)

PropTypeDefaultDescription`:routes``array`**Required**Array of route config objects (see above).`id``string`UUIDUnique route group identifier.`:selected-route``int|string``0`Index or ID of the initially selected route.`:fit-bounds``bool``false`Auto-fit map bounds to include all routes.`alternative-color``string``'#94A3B8'`Color of non-selected (alternative) routes.`:alternative-opacity``float``0.5`Opacity of non-selected routes.`:alternative-width``int``3`Width of non-selected routes.`line-cap``string``'round'`Line cap style (`'butt'`, `'round'`, `'square'`).`line-join``string``'round'`Line join style (`'bevel'`, `'round'`, `'miter'`).`:clickable``bool``true`Allow clicking routes to select them.### Dynamic Route Group Updates

[](#dynamic-route-group-updates)

Update the route group data without a full re-render:

```
$this->dispatch("map:update-route-group-{$groupId}", [
    'routes' => $updatedRoutes,
    'selectedRoute' => 1,
]);
```

### Events

[](#events)

EventDetailDescription`map:route-group-selection-changed``groupId, routeIndex`Fired when a user clicks a different route.---

Route List (``)
---------------------------------

[](#route-list-x-map-route-list)

An overlay UI panel that displays route alternatives with distance, duration, and selection. Pairs with `` (with `:alternatives="true"`) or ``.

### Usage

[](#usage-5)

```

```

### Props

[](#props-6)

PropTypeDefaultDescription`route-id``string``''`ID of the route or route group to display alternatives for.`map-id``string``''`ID of the map (if needed for multi-map pages).`:show-distance``bool``true`Show distance for each route.`:show-duration``bool``true`Show duration for each route.`:show-fastest-badge``bool``true`Highlight the fastest route with a badge.`:show-time-diff``bool``true`Show time difference compared to the fastest route.`position``string``'top-left'`Position: `top-left`, `top-right`, `bottom-left`, `bottom-right`.`title``string``'Routes'`Title shown above the route list.### Events

[](#events-1)

EventDetailDescription`map:route-list-selected``routeIndex`Fired when a user selects a route from the list.---

Clusters (``)
----------------------------------

[](#clusters-x-map-cluster-layer)

Efficiently handle thousands of markers by clustering them.

### Usage

[](#usage-6)

```
{{-- From an array --}}

{{-- From a GeoJSON URL --}}

```

### Props

[](#props-7)

PropTypeDefaultDescription`:data``array``[]`Array of `['lat' => ..., 'lng' => ..., 'properties' => [...]]` items or raw GeoJSON Features.`url``string``null`URL to a GeoJSON file. MapLibre fetches it client-side. Use instead of `:data`.`id``string`UUIDUnique cluster layer identifier.`:cluster-max-zoom``int``14`Max zoom level to cluster at.`:cluster-radius``int``50`Pixel radius to cluster points together.`:cluster-min-points``int``2`Minimum points to form a cluster.`cluster-color``string``'#1A56DB'`Color of the cluster circle.`cluster-text-color``string``'#FFFFFF'`Color of the count text inside clusters.`:cluster-size-stops``array``[[0, 30], [100, 40], [1000, 50]]`Cluster circle size stops `[[count, radius], ...]`.`point-color``string``'#1A56DB'`Color of unclustered point circles.`:point-radius``int``6`Radius of unclustered point circles.`:show-count``bool``true`Show the point count inside clusters.`popup-property``string``null`Feature property to use as the popup title (auto-styled).`popup-template``string``null`HTML string with `{property}` placeholders for custom popups.`:click-zoom``bool``true`Zoom into a cluster when clicked.`:buffer``int``256`GeoJSON source tile buffer size (higher = smoother panning).`:tolerance``float``0.5`Geometry simplification tolerance (higher = faster tiles).`:max-features-to-inline``int``2000`Feature count threshold before switching to JS-based data injection.`class``string``''`Additional CSS classes.### Popup Slot (Recommended)

[](#popup-slot-recommended)

Use the `popup` slot for full HTML control over the point popup. Property values are interpolated via `{propertyName}` placeholders. `{lat}` and `{lng}` are available as special tokens.

```

            {name}
            {address}

                ⭐ {rating}
                📞 {phone}

            {lat}, {lng}

```

### Popup Template (Attribute)

[](#popup-template-attribute)

Alternatively, pass an HTML string with `{property}` placeholders as an attribute:

```

```

### Popup Priority

[](#popup-priority)

1. **``** — Full slot control with Blade HTML
2. **`popup-template="..."`** — Inline HTML attribute with placeholders
3. **`popup-property="name"`** — Auto-styled card using one property as title
4. **Default** — Shows name/title/label (if present) plus lat/lng coordinates

### Dynamic Data Updates

[](#dynamic-data-updates)

To update cluster data without a full re-render, dispatch a Livewire event:

```
// In your Livewire component
$this->dispatch("map:update-cluster-data-{$clusterId}",
    \Kwasii\LivewireMapcn\Support\GeoJSON::fromArray($filteredData)
);
```

---

Advanced Usage
--------------

[](#advanced-usage)

### Livewire Interactivity

[](#livewire-interactivity)

The package dispatches events to Livewire and listens for specific commands.

#### Events Dispatched (Outbound)

[](#events-dispatched-outbound)

##### Map Events

[](#map-events)

EventDetailDescription`map:loaded`—Map style is fully loaded and ready.`map:click``lat, lng, detail`Map was clicked.`map:double-click``lat, lng, detail`Map was double-clicked.`map:right-click``lat, lng, detail`Map was right-clicked (context menu).`map:move``lat, lng`Throttled (100ms) — fired continuously as map moves.`map:center-changed``lat, lng`Fired once movement ends.`map:zoom``zoom`Throttled (100ms) — fired continuously during zoom.`map:zoom-changed``zoom`Fired once zoom ends.`map:bounds-changed``bounds`Fired when map bounds change.`map:drag-end``lat, lng`Fired when map drag ends.`map:bearing-changed``bearing`Throttled (100ms) — fired when map is rotated.`map:pitch-changed``pitch`Throttled (100ms) — fired when map is tilted.`map:style-loaded`—Fired when map style finishes loading.##### Locate Events

[](#locate-events)

EventDetailDescription`map:locate-success``lat, lng, accuracy`Geolocation succeeded.`map:locate-error``error`Geolocation failed.##### Marker Events

[](#marker-events)

EventDetailDescription`map:marker-clicked``id, lat, lng`Marker was clicked.`map:marker-drag-start``id, lat, lng`Marker drag started.`map:marker-drag``id, lat, lng`Marker is being dragged (continuous).`map:marker-drag-end``id, lat, lng`Marker drag ended.`map:marker-mouseenter``id, lat, lng`Mouse entered marker.`map:marker-mouseleave``id, lat, lng`Mouse left marker.`map:marker-popup-open``id`Marker popup opened.`map:marker-popup-close``id`Marker popup closed.##### Popup Events

[](#popup-events)

EventDetailDescription`map:popup-open``id`Standalone popup opened.`map:popup-close``id`Standalone popup closed.##### Route Events

[](#route-events)

EventDetailDescription`map:route-clicked``id`Route line was clicked.`map:route-mouseenter``id`Mouse entered route line.`map:route-mouseleave``id`Mouse left route line.`map:route-directions-ready``id, distance, duration, ...`OSRM directions fetched successfully.`map:route-directions-error``id, error`OSRM directions fetch failed.`map:route-alternative-selected``id, alternativeIndex`User selected an alternative route.`map:route-updated``id`Route data was updated via Livewire event.##### Route Group Events

[](#route-group-events)

EventDetailDescription`map:route-group-selection-changed``groupId, routeIndex`User clicked a different route in group.##### Cluster Events

[](#cluster-events)

EventDetailDescription`map:cluster-clicked``clusterId, lat, lng`A cluster circle was clicked.`map:cluster-expanded``clusterId`A cluster was expanded (zoomed into).`map:cluster-point-clicked``properties, lat, lng`An individual unclustered point clicked.##### Route List Events

[](#route-list-events)

EventDetailDescription`map:route-list-selected``routeIndex`User selected a route from the route list panel.##### Custom Events

[](#custom-events)

You can forward any MapLibre event by adding event names to the `:events` prop or the `custom_events` config array. They are dispatched as `map:{event-name}`.

```

```

#### Commands Listened (Inbound)

[](#commands-listened-inbound)

You can trigger these from your Livewire component using `$this->dispatch()`:

CommandPayloadDescription`map:fly-to``center, zoom, bearing, pitch, essential`Smooth animated move to a new location.`map:jump-to``center, zoom, bearing, pitch`Instant (non-animated) move to a new location.`map:fit-bounds``bounds, padding, maxZoom`Fit the map view to specific bounds.`map:set-zoom``zoom`Change zoom level.`map:set-bearing``bearing`Set the map bearing (rotation).`map:set-pitch``pitch`Set the map pitch (tilt).`map:set-style``style`Change the map style (URL or JSON).`map:resize`—Force map recalculation (useful for hidden containers).`map:force-animate`—Force re-trigger route animations.`map:call``method, ...args`Call any MapLibre GL JS method directly.##### Dynamic Data Commands

[](#dynamic-data-commands)

CommandPayloadDescription`map:update-route-data-{id}``coordinates`Update a route's coordinates dynamically.`map:update-cluster-data-{id}`GeoJSON dataUpdate cluster data without full re-render.`map:update-route-group-{id}``routes, ...`Update route group configuration.#### Example: Fly To Location

[](#example-fly-to-location)

```
// In Livewire Component
public function centerOnPilot()
{
    $this->dispatch('map:fly-to', [
        'center' => [-0.09, 51.5],
        'zoom' => 12,
        'essential' => true,
    ]);
}
```

#### Example: Call MapLibre Method Directly

[](#example-call-maplibre-method-directly)

```
// In Livewire Component
public function setMaxZoom()
{
    $this->dispatch('map:call', [
        'method' => 'setMaxZoom',
        'args' => [18],
    ]);
}
```

### Theme Awareness

[](#theme-awareness)

By default, the map follows the `.dark` class on your `html` element if `theme="auto"` is set. You can also force a specific theme using `theme="light"` or `theme="dark"`.

You can provide separate style URLs for light and dark modes:

```

```

### Controlled Viewport

[](#controlled-viewport)

You can track and control the map viewport (center, zoom, bearing, pitch) by listening to events and using Alpine.js for real-time reactivity, similar to React's `onViewportChange`.

#### Example: Reactive Viewport Dashboard

[](#example-reactive-viewport-dashboard)

```

        lng:
        lat:
        zoom:
        bearing: °
        pitch: °

```

#### Event Reference for Viewport

[](#event-reference-for-viewport)

EventDetailDescription`map:move``lat, lng`Throttled (100ms) — fired continuously as the map moves.`map:center-changed``lat, lng`Fired once movement ends.`map:zoom``zoom`Throttled (100ms) — fired continuously during zoom.`map:zoom-changed``zoom`Fired once zoom ends.`map:bearing-changed``bearing`Throttled (100ms) — fired when the map is rotated.`map:pitch-changed``pitch`Throttled (100ms) — fired when the map is tilted.---

### Alpine.js Directives

[](#alpinejs-directives)

The package registers the following Alpine.js directives:

DirectiveDescription`x-map`Creates the MapLibre GL map instance with full configuration.`x-map-controls`Adds navigation, geolocate, fullscreen, and scale controls.`x-map-marker`Creates a marker with support for custom content and events.`x-map-popup`Creates a standalone popup anchored to coordinates.`x-map-route`Renders route lines with OSRM directions and animation support.`x-map-route-group`Manages multiple selectable routes on the same map.`x-map-route-list`Renders a route selection UI panel.`x-map-cluster-layer`GeoJSON clustering with popups and dynamic data updates.`x-map-resize`Triggers map resize when the bound expression changes.`x-map-marker-popup`Sub-directive for marker popup configuration.`x-map-marker-tooltip`Sub-directive for marker tooltip configuration.### GeoJSON Helper

[](#geojson-helper)

The `GeoJSON::fromArray()` helper converts simple PHP arrays into GeoJSON FeatureCollections:

```
use Kwasii\LivewireMapcn\Support\GeoJSON;

$geoJson = GeoJSON::fromArray([
    ['lat' => 51.505, 'lng' => -0.09, 'properties' => ['name' => 'Location 1']],
    ['lat' => 51.51,  'lng' => -0.1,  'properties' => ['name' => 'Location 2']],
]);

// Also passes through existing GeoJSON Feature objects:
$geoJson = GeoJSON::fromArray([
    ['type' => 'Feature', 'geometry' => [...], 'properties' => [...]],
]);
```

---

### Performance Tips

[](#performance-tips)

- **Use clusters for large datasets**: Always use `` instead of individual `` tags for datasets over ~100 points.
- **Tune cluster radius**: Larger `:cluster-radius` values (e.g., `80`) produce fewer clusters and faster rendering.
- **Lower cluster max zoom**: Setting `:cluster-max-zoom="12"` stops unclustering at lower zoom levels, reducing visible point counts.
- **Cluster size stops**: Customize `:cluster-size-stops` to control circle sizes at different point counts.
- **Increase tolerance**: `:tolerance="0.8"` simplifies geometries for faster tile generation at the cost of precision.
- **Increase buffer**: `:buffer="512"` reduces tile-edge artefacts during fast panning (uses more memory).
- **Throttled events**: Continuous map events (`map:move`, `map:zoom`, `map:bearing-changed`, `map:pitch-changed`) are throttled to 100ms to prevent frame drops. Final values are still delivered via `moveend`/`zoomend` events.
- **Dynamic updates**: Use `map:update-cluster-data-{id}`, `map:update-route-data-{id}`, and `map:update-route-group-{id}` Livewire events to update data without re-rendering the entire component.
- **Inline threshold**: The `:max-features-to-inline` prop (default `2000`) controls whether cluster GeoJSON data is embedded in HTML attributes or injected via JavaScript for better performance with large datasets.

---

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance94

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity57

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

Every ~2 days

Total

5

Last Release

65d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/72253336?v=4)[kwasii](/maintainers/kwasii)[@kwasii](https://github.com/kwasii)

---

Top Contributors

[![kwasii1](https://avatars.githubusercontent.com/u/84879506?v=4)](https://github.com/kwasii1 "kwasii1 (31 commits)")

---

Tags

laravelkwasiilivewire-mapcn

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/kwasii-livewire-mapcn/health.svg)

```
[![Health](https://phpackages.com/badges/kwasii-livewire-mapcn/health.svg)](https://phpackages.com/packages/kwasii-livewire-mapcn)
```

###  Alternatives

[leandrocfe/filament-apex-charts

Apex Charts integration for Filament PHP.

4861.2M8](/packages/leandrocfe-filament-apex-charts)[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[spatie/livewire-filepond

Upload files using Filepond in Livewire components

306452.7k3](/packages/spatie-livewire-filepond)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24149.7k](/packages/vormkracht10-laravel-mails)[ralphjsmit/livewire-urls

Get the previous and current url in Livewire.

82270.3k4](/packages/ralphjsmit-livewire-urls)[codebar-ag/laravel-filament-json-field

A Laravel Filament JSON Field integration with CodeMirror support

1124.1k](/packages/codebar-ag-laravel-filament-json-field)

PHPackages © 2026

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