MoonShine Yandex Maps
The fields package for MoonShine 4.x — working with maps and polygons via Yandex Maps API.

Features
- YandexMap — points with markers, balloons, custom content
- YandexMapPolygon — drawing polygons, delivery zones, areas
Requirements
- PHP 8.2+
- Laravel 11+
- MoonShine 4.x
- API key for Yandex.Maps
Installation
composer require goodappr/moonshine-yandex-maps
composer require goodappr/moonshine-yandex-maps
composer require goodappr/moonshine-yandex-maps
composer require goodappr/moonshine-yandex-maps
composer require goodappr/moonshine-yandex-maps
Configuration
Publish the config and set the API key:
php artisan vendor:publish --tag=moonshine-yandex-maps-config
php artisan vendor:publish --tag=moonshine-yandex-maps-config
php artisan vendor:publish --tag=moonshine-yandex-maps-config
php artisan vendor:publish --tag=moonshine-yandex-maps-config
php artisan vendor:publish --tag=moonshine-yandex-maps-config
In .env:
YANDEX_MAPS_API_KEY=your_yandex_maps_api_key
YANDEX_MAPS_API_KEY=your_yandex_maps_api_key
YANDEX_MAPS_API_KEY=your_yandex_maps_api_key
YANDEX_MAPS_API_KEY=your_yandex_maps_api_key
YANDEX_MAPS_API_KEY=your_yandex_maps_api_key
Or add to config/services.php:
'yandex' => [
'maps_api_key' => env('YANDEX_MAPS_API_KEY', ''),
],
'yandex' => [
'maps_api_key' => env('YANDEX_MAPS_API_KEY', ''),
],
'yandex' => [
'maps_api_key' => env('YANDEX_MAPS_API_KEY', ''),
],
'yandex' => [
'maps_api_key' => env('YANDEX_MAPS_API_KEY', ''),
],
'yandex' => [
'maps_api_key' => env('YANDEX_MAPS_API_KEY', ''),
],
Usage
YandexMap — points on the map
use MoonShine\YandexMaps\Fields\YandexMap;
use MoonShine\UI\Fields\Text;
use MoonShine\UI\Fields\Textarea;
use MoonShine\UI\Fields\Select;
use MoonShine\UI\Fields\Color;
use MoonShine\UI\Fields\Image;
YandexMap::make('Location', 'location')
->coordinates([55.751574, 37.573856])
->zoom(12)
->mapHeight('400px')
->indexDisplayFields(['address', 'phone', 'email'])
->indexShowAddressCopy(true)
->balloonContent([
'title' => 'model.name',
'address' => 'model.address',
'phone' => 'model.phone',
])
->placemarkProperties([
'hintContent' => 'Click to view',
'iconCaption' => 'Branch',
])
->placemarkOptions([
'preset' => Select::make('Icon type', 'icon_type')
->options([
'islands#blueHomeIcon' => 'House',
'islands#redRestaurantIcon' => 'Restaurant',
])
->default('islands#blueHomeIcon'),
'iconColor' => Color::make('Color', 'icon_color')->default('#3B82F6'),
'iconImageHref' => Image::make('Custom icon', 'iconImageHref')
->dir('icons')
->allowedExtensions(['png', 'svg', 'webp']),
'draggable' => true,
])
->customBalloonFields([
Text::make('Balloon title', 'title')->default('Object'),
Textarea::make('Description', 'description'),
]);
use MoonShine\YandexMaps\Fields\YandexMap;
use MoonShine\UI\Fields\Text;
use MoonShine\UI\Fields\Textarea;
use MoonShine\UI\Fields\Select;
use MoonShine\UI\Fields\Color;
use MoonShine\UI\Fields\Image;
YandexMap::make('Location', 'location')
->coordinates([55.751574, 37.573856])
->zoom(12)
->mapHeight('400px')
->indexDisplayFields(['address', 'phone', 'email'])
->indexShowAddressCopy(true)
->balloonContent([
'title' => 'model.name',
'address' => 'model.address',
'phone' => 'model.phone',
])
->placemarkProperties([
'hintContent' => 'Click to view',
'iconCaption' => 'Branch',
])
->placemarkOptions([
'preset' => Select::make('Icon type', 'icon_type')
->options([
'islands#blueHomeIcon' => 'House',
'islands#redRestaurantIcon' => 'Restaurant',
])
->default('islands#blueHomeIcon'),
'iconColor' => Color::make('Color', 'icon_color')->default('#3B82F6'),
'iconImageHref' => Image::make('Custom icon', 'iconImageHref')
->dir('icons')
->allowedExtensions(['png', 'svg', 'webp']),
'draggable' => true,
])
->customBalloonFields([
Text::make('Balloon title', 'title')->default('Object'),
Textarea::make('Description', 'description'),
]);
use MoonShine\YandexMaps\Fields\YandexMap;
use MoonShine\UI\Fields\Text;
use MoonShine\UI\Fields\Textarea;
use MoonShine\UI\Fields\Select;
use MoonShine\UI\Fields\Color;
use MoonShine\UI\Fields\Image;
YandexMap::make('Location', 'location')
->coordinates([55.751574, 37.573856])
->zoom(12)
->mapHeight('400px')
->indexDisplayFields(['address', 'phone', 'email'])
->indexShowAddressCopy(true)
->balloonContent([
'title' => 'model.name',
'address' => 'model.address',
'phone' => 'model.phone',
])
->placemarkProperties([
'hintContent' => 'Click to view',
'iconCaption' => 'Branch',
])
->placemarkOptions([
'preset' => Select::make('Icon type', 'icon_type')
->options([
'islands#blueHomeIcon' => 'House',
'islands#redRestaurantIcon' => 'Restaurant',
])
->default('islands#blueHomeIcon'),
'iconColor' => Color::make('Color', 'icon_color')->default('#3B82F6'),
'iconImageHref' => Image::make('Custom icon', 'iconImageHref')
->dir('icons')
->allowedExtensions(['png', 'svg', 'webp']),
'draggable' => true,
])
->customBalloonFields([
Text::make('Balloon title', 'title')->default('Object'),
Textarea::make('Description', 'description'),
]);
use MoonShine\YandexMaps\Fields\YandexMap;
use MoonShine\UI\Fields\Text;
use MoonShine\UI\Fields\Textarea;
use MoonShine\UI\Fields\Select;
use MoonShine\UI\Fields\Color;
use MoonShine\UI\Fields\Image;
YandexMap::make('Location', 'location')
->coordinates([55.751574, 37.573856])
->zoom(12)
->mapHeight('400px')
->indexDisplayFields(['address', 'phone', 'email'])
->indexShowAddressCopy(true)
->balloonContent([
'title' => 'model.name',
'address' => 'model.address',
'phone' => 'model.phone',
])
->placemarkProperties([
'hintContent' => 'Click to view',
'iconCaption' => 'Branch',
])
->placemarkOptions([
'preset' => Select::make('Icon type', 'icon_type')
->options([
'islands#blueHomeIcon' => 'House',
'islands#redRestaurantIcon' => 'Restaurant',
])
->default('islands#blueHomeIcon'),
'iconColor' => Color::make('Color', 'icon_color')->default('#3B82F6'),
'iconImageHref' => Image::make('Custom icon', 'iconImageHref')
->dir('icons')
->allowedExtensions(['png', 'svg', 'webp']),
'draggable' => true,
])
->customBalloonFields([
Text::make('Balloon title', 'title')->default('Object'),
Textarea::make('Description', 'description'),
]);
use MoonShine\YandexMaps\Fields\YandexMap;
use MoonShine\UI\Fields\Text;
use MoonShine\UI\Fields\Textarea;
use MoonShine\UI\Fields\Select;
use MoonShine\UI\Fields\Color;
use MoonShine\UI\Fields\Image;
YandexMap::make('Location', 'location')
->coordinates([55.751574, 37.573856])
->zoom(12)
->mapHeight('400px')
->indexDisplayFields(['address', 'phone', 'email'])
->indexShowAddressCopy(true)
->balloonContent([
'title' => 'model.name',
'address' => 'model.address',
'phone' => 'model.phone',
])
->placemarkProperties([
'hintContent' => 'Click to view',
'iconCaption' => 'Branch',
])
->placemarkOptions([
'preset' => Select::make('Icon type', 'icon_type')
->options([
'islands#blueHomeIcon' => 'House',
'islands#redRestaurantIcon' => 'Restaurant',
])
->default('islands#blueHomeIcon'),
'iconColor' => Color::make('Color', 'icon_color')->default('#3B82F6'),
'iconImageHref' => Image::make('Custom icon', 'iconImageHref')
->dir('icons')
->allowedExtensions(['png', 'svg', 'webp']),
'draggable' => true,
])
->customBalloonFields([
Text::make('Balloon title', 'title')->default('Object'),
Textarea::make('Description', 'description'),
]);

The data is saved in JSON: lat, lng, coordinates, balloon_data, placemark_options, placemark_properties.
YandexMapPolygon — polygons
use MoonShine\YandexMaps\Fields\YandexMapPolygon;
YandexMapPolygon::make('Delivery zones', 'delivery_zones')
->mapHeight('300px')
->allowMultiplePolygons()
->allowEditExisting()
->allowImportExport()
->defaultPolygonColor('#3B82F6')
->defaultPolygonOpacity(0.3)
->polygonColors(['#3B82F6', '#10B981', '#F59E0B', '#EF4444'])
->showMiniMapOnIndex();
use MoonShine\YandexMaps\Fields\YandexMapPolygon;
YandexMapPolygon::make('Delivery zones', 'delivery_zones')
->mapHeight('300px')
->allowMultiplePolygons()
->allowEditExisting()
->allowImportExport()
->defaultPolygonColor('#3B82F6')
->defaultPolygonOpacity(0.3)
->polygonColors(['#3B82F6', '#10B981', '#F59E0B', '#EF4444'])
->showMiniMapOnIndex();
use MoonShine\YandexMaps\Fields\YandexMapPolygon;
YandexMapPolygon::make('Delivery zones', 'delivery_zones')
->mapHeight('300px')
->allowMultiplePolygons()
->allowEditExisting()
->allowImportExport()
->defaultPolygonColor('#3B82F6')
->defaultPolygonOpacity(0.3)
->polygonColors(['#3B82F6', '#10B981', '#F59E0B', '#EF4444'])
->showMiniMapOnIndex();
use MoonShine\YandexMaps\Fields\YandexMapPolygon;
YandexMapPolygon::make('Delivery zones', 'delivery_zones')
->mapHeight('300px')
->allowMultiplePolygons()
->allowEditExisting()
->allowImportExport()
->defaultPolygonColor('#3B82F6')
->defaultPolygonOpacity(0.3)
->polygonColors(['#3B82F6', '#10B981', '#F59E0B', '#EF4444'])
->showMiniMapOnIndex();
use MoonShine\YandexMaps\Fields\YandexMapPolygon;
YandexMapPolygon::make('Delivery zones', 'delivery_zones')
->mapHeight('300px')
->allowMultiplePolygons()
->allowEditExisting()
->allowImportExport()
->defaultPolygonColor('#3B82F6')
->defaultPolygonOpacity(0.3)
->polygonColors(['#3B82F6', '#10B981', '#F59E0B', '#EF4444'])
->showMiniMapOnIndex();

Connecting assets for Layout
To copy the address on click and correctly send long polygon data, add the trait to your Layout:
namespace App\MoonShine\Layouts;
use MoonShine\YandexMaps\Traits\WithYandexMapsAssets;
use MoonShine\Laravel\Layouts\AppLayout;
class MoonShineLayout extends AppLayout
{
use WithYandexMapsAssets;
protected function assets(): array
{
return [
...parent::assets(),
...$this->getYandexMapsAssets(),
];
}
}
namespace App\MoonShine\Layouts;
use MoonShine\YandexMaps\Traits\WithYandexMapsAssets;
use MoonShine\Laravel\Layouts\AppLayout;
class MoonShineLayout extends AppLayout
{
use WithYandexMapsAssets;
protected function assets(): array
{
return [
...parent::assets(),
...$this->getYandexMapsAssets(),
];
}
}
namespace App\MoonShine\Layouts;
use MoonShine\YandexMaps\Traits\WithYandexMapsAssets;
use MoonShine\Laravel\Layouts\AppLayout;
class MoonShineLayout extends AppLayout
{
use WithYandexMapsAssets;
protected function assets(): array
{
return [
...parent::assets(),
...$this->getYandexMapsAssets(),
];
}
}
namespace App\MoonShine\Layouts;
use MoonShine\YandexMaps\Traits\WithYandexMapsAssets;
use MoonShine\Laravel\Layouts\AppLayout;
class MoonShineLayout extends AppLayout
{
use WithYandexMapsAssets;
protected function assets(): array
{
return [
...parent::assets(),
...$this->getYandexMapsAssets(),
];
}
}
namespace App\MoonShine\Layouts;
use MoonShine\YandexMaps\Traits\WithYandexMapsAssets;
use MoonShine\Laravel\Layouts\AppLayout;
class MoonShineLayout extends AppLayout
{
use WithYandexMapsAssets;
protected function assets(): array
{
return [
...parent::assets(),
...$this->getYandexMapsAssets(),
];
}
}
Data Structure
YandexMap (location)
{
"lat": 55.751574,
"lng": 37.573856,
"coordinates": [55.751574, 37.573856],
"balloon_data": { "title": "...", "description": "..." },
"placemark_options": { "preset": "...", "iconImageHref": "..." },
"placemark_properties": { "hintContent": "...", "iconCaption": "..." }
}
{
"lat": 55.751574,
"lng": 37.573856,
"coordinates": [55.751574, 37.573856],
"balloon_data": { "title": "...", "description": "..." },
"placemark_options": { "preset": "...", "iconImageHref": "..." },
"placemark_properties": { "hintContent": "...", "iconCaption": "..." }
}
{
"lat": 55.751574,
"lng": 37.573856,
"coordinates": [55.751574, 37.573856],
"balloon_data": { "title": "...", "description": "..." },
"placemark_options": { "preset": "...", "iconImageHref": "..." },
"placemark_properties": { "hintContent": "...", "iconCaption": "..." }
}
{
"lat": 55.751574,
"lng": 37.573856,
"coordinates": [55.751574, 37.573856],
"balloon_data": { "title": "...", "description": "..." },
"placemark_options": { "preset": "...", "iconImageHref": "..." },
"placemark_properties": { "hintContent": "...", "iconCaption": "..." }
}
{
"lat": 55.751574,
"lng": 37.573856,
"coordinates": [55.751574, 37.573856],
"balloon_data": { "title": "...", "description": "..." },
"placemark_options": { "preset": "...", "iconImageHref": "..." },
"placemark_properties": { "hintContent": "...", "iconCaption": "..." }
}
YandexMapPolygon (GeoJSON-like)
[
{
"type": "Polygon",
"coordinates": [[[lng, lat], [lng, lat], ...]],
"style": { "fillColor": "#3B82F6", "strokeColor": "#1D4ED8" },
"data": { "name": "Zone 1" }
}
]
[
{
"type": "Polygon",
"coordinates": [[[lng, lat], [lng, lat], ...]],
"style": { "fillColor": "#3B82F6", "strokeColor": "#1D4ED8" },
"data": { "name": "Zone 1" }
}
]
[
{
"type": "Polygon",
"coordinates": [[[lng, lat], [lng, lat], ...]],
"style": { "fillColor": "#3B82F6", "strokeColor": "#1D4ED8" },
"data": { "name": "Zone 1" }
}
]
[
{
"type": "Polygon",
"coordinates": [[[lng, lat], [lng, lat], ...]],
"style": { "fillColor": "#3B82F6", "strokeColor": "#1D4ED8" },
"data": { "name": "Zone 1" }
}
]
[
{
"type": "Polygon",
"coordinates": [[[lng, lat], [lng, lat], ...]],
"style": { "fillColor": "#3B82F6", "strokeColor": "#1D4ED8" },
"data": { "name": "Zone 1" }
}
]
Migrations
For storage:
$table->json('location')->nullable();
$table->json('delivery_zones')->nullable();
$table->json('location')->nullable();
$table->json('delivery_zones')->nullable();
$table->json('location')->nullable();
$table->json('delivery_zones')->nullable();
$table->json('location')->nullable();
$table->json('delivery_zones')->nullable();
$table->json('location')->nullable();
$table->json('delivery_zones')->nullable();
License
MIT