Map
The map package renders interactive maps from server-defined features. The public PHP and wire APIs use coordinates, providers, and typed features rather than provider concepts. OpenStreetMap and Google Maps are the built-in providers; another package can add its own provider without changing page definitions.
The package supports markers and routes. A marker can display any Lattice component schema in a popup, including links, forms, and registered actions. A route draws a server-supplied path as a line; computing that path is the application’s concern. Polygons, editing, geocoding, and clustering are outside the API.
Installation
Section titled “Installation”composer require lattice-php/mapComposer is the only install. The lattice() Vite plugin discovers the package through Composer
and adds only a small entry to the app bundle: the map component and its precompiled renderers —
with Leaflet bundled inside, while React and the Lattice runtime remain shared with the host
app — load on demand the first time a page renders a map, so pages without a map never pay for
Leaflet. For a no-build app, run php artisan lattice:assets after
installation; it publishes the same self-contained renderer as a single standalone plugin.
In an app with a build step, import the map stylesheet in your application CSS — it positions the Leaflet panes and themes the controls, markers, and popups with the Lattice design tokens:
@import "@lattice-php/map/css";Map::make('offices') ->height(360) ->markers([ Marker::make('berlin') ->position(52.5200, 13.4050) ->label('Berlin office') ->popup([ Stack::make()->gap(Gap::Small)->schema([ Heading::make('Berlin office', 3), Text::make('Alexanderplatz 1'), ]), ]) ->open(), Marker::make('hamburg') ->position(53.5511, 9.9937) ->label('Hamburg office') ->color(ColorName::Warning), ]);- center:null
- height:360
- navigationControls:true
- provider:{"maximumZoom":19,"minimumZoom":1,"name":"openstreetmap","options":{"attribution":"© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors","tileUrl":"https://tile.openstreetmap.org/{z}/{x}/{y}.png"}}
- scrollZoom:false
- zoom:null
- align:null
- direction:null
- float:null
- gap:"sm"
- height:null
- justify:null
- sticky:false
- width:null
- copyable:false
- level:3
- text:"Berlin office"
- tooltip:null
- align:null
- color:null
- copyable:false
- size:"md"
- text:"Alexanderplatz 1"
->open() marks one popup for automatic opening after the map initializes. Only one marker may be
open initially, and marker IDs must be unique. Labels supply each marker’s accessible name even
when the popup schema renders different text.
->icon() replaces the pin’s dot with any Lattice icon (a Lattice\Ui\Enums\Icon case, or the
sprite id of an app-registered icon), and ->color() tints the pin with a named Lattice color or
a CSS color. Markers without either keep the primary pin with the plain dot.
Without an explicit center, one marker opens at a practical street-level zoom and several markers are fitted into view. An empty map shows the world. Override the viewport and controls when needed:
Map::make('service-area') ->center(latitude: 52.52, longitude: 13.405) ->zoom(11) ->height(520) ->scrollZoom() ->navigationControls(false) ->markers($markers);Scroll-wheel zoom is disabled by default so a map embedded in a page does not capture normal page
scrolling — holding Cmd/Ctrl while scrolling (or a trackpad pinch) still zooms the map;
->scrollZoom() makes the plain wheel zoom too. Zoom values must fit both the general 0–24
range and the active provider’s range.
When a default zoom is set with ->zoom(), the map shows a reset control below the zoom buttons
that returns the viewport to its initial center and zoom after panning or zooming away.
->navigationControls(false) hides it together with the zoom buttons.
Routes
Section titled “Routes”->routes() draws server-supplied paths as lines on the map. A route takes a list of coordinates —
[latitude, longitude] pairs or CoordinateData instances — and optional styling. Routes take part
in the automatic viewport fit exactly like markers:
Map::make('commute') ->height(360) ->routes([ Route::make('berlin-potsdam') ->path([ [52.5200, 13.4050], [52.5063, 13.3320], [52.4581, 13.2107], [52.3989, 13.0657], ]) ->color(ColorName::Info) ->weight(4), ]) ->markers([ Marker::make('berlin') ->position(52.5200, 13.4050) ->label('Berlin office'), Marker::make('potsdam') ->position(52.3989, 13.0657) ->label('Potsdam office'), ]);- center:null
- height:360
- navigationControls:true
- provider:{"maximumZoom":19,"minimumZoom":1,"name":"openstreetmap","options":{"attribution":"© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors","tileUrl":"https://tile.openstreetmap.org/{z}/{x}/{y}.png"}}
- scrollZoom:false
- zoom:null
A route needs at least two points and an id that is unique across all features on the map, markers
included. ->color() accepts the same named Lattice colors and CSS colors as markers; without one
the route uses the primary color. ->weight() sets the stroke width in pixels.
OpenStreetMap Tiles
Section titled “OpenStreetMap Tiles”The built-in provider uses the public OpenStreetMap tile service and includes the required attribution. This default is convenient for development and modest interactive use, but the public service has no SLA and is not a free general-purpose CDN. Production applications must follow the OpenStreetMap tile usage policy, keep attribution visible, and use a suitable commercial or self-hosted tile service when traffic or availability requirements demand it.
Override the tile endpoint without changing map definitions:
In config/map.php:
return [ 'default_provider' => 'openstreetmap', 'providers' => [ 'openstreetmap' => [ 'tile_url' => env('MAP_TILE_URL', 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'), 'attribution' => '© OpenStreetMap contributors', 'minimum_zoom' => 1, 'maximum_zoom' => 19, ], ],];Google Maps
Section titled “Google Maps”The Google Maps provider ships with the package and activates once an API key is configured:
GOOGLE_MAPS_API_KEY=your-browser-keySelect it per map with Map::make()->provider('googlemaps'), or make it the app-wide default with
'default_provider' => 'googlemaps' in config/map.php. Markers, popups, routes, viewport, and
controls behave exactly as on OpenStreetMap; the provider supports zoom levels 0–22. Without a
configured key the provider is not registered, so unconfigured apps keep working with
OpenStreetMap alone.
The renderer loads the Google Maps JavaScript API from maps.googleapis.com at runtime — nothing
Google-specific is bundled. If your app sets a Content Security Policy, allow that origin for
scripts and its tile hosts for images.
Markers render as Advanced Markers,
which require a map id. The provider defaults to Google’s DEMO_MAP_ID:
GOOGLE_MAPS_MAP_ID=your-map-idAdding a Provider
Section titled “Adding a Provider”A provider has one server and one client registration. The server implementation returns its stable name, provider-specific browser options, and supported zoom range:
use Lattice\Map\Contracts\MapProvider;use Lattice\Map\MapProviderData;use Lattice\Map\MapProviderRegistry;
final class MapboxProvider implements MapProvider{ public function data(): MapProviderData { return new MapProviderData( name: 'mapbox', options: ['accessToken' => config('services.mapbox.token')], minimumZoom: 0, maximumZoom: 22, ); }}
app(MapProviderRegistry::class)->register(app(MapboxProvider::class));Its Lattice plugin registers a React component under the matching map.providers key:
import type { Plugin } from "@lattice-php/core";import MapboxMap from "./mapbox-map";
export default { name: "acme/mapbox", extensions: { "map.providers": { mapbox: MapboxMap, }, },} satisfies Plugin;Applications then select it with Map::make()->provider('mapbox'). The map component keeps the
same markers, routes, popup schemas, viewport, and controls contract; only the provider options and
renderer change. The isMarkerFeature and isRouteFeature guards exported from
@lattice-php/map narrow the wire features to the type a renderer is drawing.
Bundle Size
Section titled “Bundle Size”The report measures the precompiled map plugin. It includes Leaflet but externalizes React and the framework runtime, so it represents the package’s additional JavaScript — loaded only when a page actually renders a map.
50.5 KB gzipped · 198.7 KB raw JavaScript
| Dependency | Raw | Gzip | Share |
|---|---|---|---|
| @lattice-php/map | 12.0 KB | 4.1 KB | 8.1% |
| leaflet | 165.8 KB | 44.8 KB | 88.7% |
| Bundler runtime | 20.8 KB | 1.6 KB | 3.2% |
Emitted JavaScript files
| File | Raw | Gzip |
|---|---|---|
plugin.js | 198.7 KB | 50.5 KB |