Внешний вид

Assets

Основы

AssetManager в MoonShine предоставляет удобный способ управления CSS и JavaScript ресурсами вашей административной панели. Он поддерживает различные типы ресурсов, включая внешние файлы, встроенный код и версионирование.

Типы ресурсов

В MoonShine есть несколько типов ресурсов:

  • MoonShine\AssetManager\Js - js через тег <script src>,
  • MoonShine\AssetManager\Css - css через тег <link>,
  • MoonShine\AssetManager\InlineCss - css через тег <style>,
  • MoonShine\AssetManager\InlineJs - js через тег <script>,
  • MoonShine\AssetManager\Raw - произвольный контент в head.

JavaScript файлы

 namespaces
use MoonShine\AssetManager\Js;
 
// Базовое подключение
Js::make('/js/app.js');
 
// С отложенной загрузкой
Js::make('/js/app.js')->defer();
 
// С атрибутами
Js::make('/js/app.js')->customAttributes([
'data-module' => 'main'
]);
 namespaces
use MoonShine\AssetManager\Js;
 
// Базовое подключение
Js::make('/js/app.js');
 
// С отложенной загрузкой
Js::make('/js/app.js')->defer();
 
// С атрибутами
Js::make('/js/app.js')->customAttributes([
'data-module' => 'main'
]);

CSS файлы

 namespaces
use MoonShine\AssetManager\Css;
 
// Базовое подключение
Css::make('/css/styles.css');
 
// С отложенной загрузкой
Css::make('/css/styles.css')->defer();
 
// С атрибутами
Css::make('/css/styles.css')->customAttributes([
'media' => 'print'
]);
 namespaces
use MoonShine\AssetManager\Css;
 
// Базовое подключение
Css::make('/css/styles.css');
 
// С отложенной загрузкой
Css::make('/css/styles.css')->defer();
 
// С атрибутами
Css::make('/css/styles.css')->customAttributes([
'media' => 'print'
]);

Встроенный JavaScript

 namespaces
use MoonShine\AssetManager\InlineJs;
 
InlineJs::make(<<<'JS'
document.addEventListener("DOMContentLoaded", function() {
console.log("Loaded");
});
JS);
 namespaces
use MoonShine\AssetManager\InlineJs;
 
InlineJs::make(<<<'JS'
document.addEventListener("DOMContentLoaded", function() {
console.log("Loaded");
});
JS);

Встроенный CSS

 namespaces
use MoonShine\AssetManager\InlineCss;
 
InlineCss::make(<<<'CSS'
.custom-class {
color: red;
}
CSS);
 namespaces
use MoonShine\AssetManager\InlineCss;
 
InlineCss::make(<<<'CSS'
.custom-class {
color: red;
}
CSS);

Raw-контент

 namespaces
use MoonShine\AssetManager\Raw;
 
Raw::make('<link rel="preconnect" href="https://fonts.googleapis.com">');
 namespaces
use MoonShine\AssetManager\Raw;
 
Raw::make('<link rel="preconnect" href="https://fonts.googleapis.com">');

Коллекции ресурсов

AssetManager позволяет управлять порядком загрузки ресурсов. Мы рекомендуем использовать DI, чтобы начать взаимодействие с AssetManager, за сервис отвечает интерфейс MoonShine\Contracts\AssetManager\AssetManagerContract. Также MoonShine предоставляет удобные методы взаимодействия с AssetManager в разных сущностях, таких как CrudResource, Page, Layout, Component и Field.

 namespaces
use MoonShine\AssetManager\Js;
 
// Добавить ресурсы в конец
$assetManager->append([
Js::make('/js/last.js')
]);
 
// Добавить ресурсы в начало
$assetManager->prepend([
Js::make('/js/first.js')
]);
 
// Добавить ресурсы в порядке добавления
$assetManager->add([
Js::make('/js/middle.js')
]);
 namespaces
use MoonShine\AssetManager\Js;
 
// Добавить ресурсы в конец
$assetManager->append([
Js::make('/js/last.js')
]);
 
// Добавить ресурсы в начало
$assetManager->prepend([
Js::make('/js/first.js')
]);
 
// Добавить ресурсы в порядке добавления
$assetManager->add([
Js::make('/js/middle.js')
]);

Метод append() всегда будет добавлять ресурсы до основного списка из CrudResource, Page, Layout, Component, Field, а prepend() после. Метод add() будет зависеть от жизненного цикла приложения. Допустим, вы добавляете ассеты в ModelResource, но перед отображением страницы будет вызван Layout, который также в свою очередь добавит ассеты, тем самым ассеты Layout добавятся в конце.

Вы также можете воспользоваться хелпером moonshine()->getAssetManager()

Модификация ресурсов

Вы можете модифицировать коллекцию ресурсов с помощью замыканий:

$assetManager->modifyAssets(function($assets) {
// Модифицируем коллекцию ресурсов
return array_filter($assets, function($asset) {
return !str_contains($asset->getLink(), 'remove-this');
});
});
$assetManager->modifyAssets(function($assets) {
// Модифицируем коллекцию ресурсов
return array_filter($assets, function($asset) {
return !str_contains($asset->getLink(), 'remove-this');
});
});

Версионирование

AssetManager поддерживает версионирование ресурсов для управления кешированием, по умолчанию будет использоваться версия MoonShine, но вы можете переопределить у конкретного ресурса:

 namespaces
use MoonShine\AssetManager\Js;
 
// Добавление версии к отдельному ресурсу
Js::make('/js/app.js')->version('1.0.0');
 
// Результат: /js/app.js?v=1.0.0
 namespaces
use MoonShine\AssetManager\Js;
 
// Добавление версии к отдельному ресурсу
Js::make('/js/app.js')->version('1.0.0');
 
// Результат: /js/app.js?v=1.0.0

Версионирование автоматически добавляет параметр v к URL ресурса. Если URL уже содержит параметры запроса, версия будет добавлена через &.

Добавление ресурсов

Глобально

// MoonShineServiceProvider
 namespaces
use MoonShine\AssetManager\Js;
use MoonShine\Contracts\AssetManager\AssetManagerContract;
use MoonShine\Contracts\Core\DependencyInjection\ConfiguratorContract;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
 
public function boot(
CoreContract $core,
ConfiguratorContract $config,
AssetManagerContract $assets,
): void
{
$assets->add(Js::make('/js/app.js'));
}
// MoonShineServiceProvider
 namespaces
use MoonShine\AssetManager\Js;
use MoonShine\Contracts\AssetManager\AssetManagerContract;
use MoonShine\Contracts\Core\DependencyInjection\ConfiguratorContract;
use MoonShine\Contracts\Core\DependencyInjection\CoreContract;
 
public function boot(
CoreContract $core,
ConfiguratorContract $config,
AssetManagerContract $assets,
): void
{
$assets->add(Js::make('/js/app.js'));
}

Шаблон

 namespaces
use Illuminate\Support\Facades\Vite;
use MoonShine\AssetManager\Js;
 
final class MoonShineLayout extends AppLayout
{
protected function assets(): array
{
return [
Js::make(Vite::asset('resources/js/app.js'))
];
}
}
 namespaces
use Illuminate\Support\Facades\Vite;
use MoonShine\AssetManager\Js;
 
final class MoonShineLayout extends AppLayout
{
protected function assets(): array
{
return [
Js::make(Vite::asset('resources/js/app.js'))
];
}
}

CrudResource

 namespaces
use MoonShine\AssetManager\InlineJs;
use MoonShine\AssetManager\Js;
 
protected function onLoad(): void
{
$this->getAssetManager()
->prepend(InlineJs::make('alert(1)'))
->append(Js::make('/js/app.js'));
}
 namespaces
use MoonShine\AssetManager\InlineJs;
use MoonShine\AssetManager\Js;
 
protected function onLoad(): void
{
$this->getAssetManager()
->prepend(InlineJs::make('alert(1)'))
->append(Js::make('/js/app.js'));
}

Page

 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
 
protected function onLoad(): void
{
parent::onLoad();
 
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
 
protected function onLoad(): void
{
parent::onLoad();
 
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}

Component

На лету

 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\UI\Components\Layout\Box;
 
Box::make()->addAssets([
Js::make('/js/custom.js'),
Css::make('/css/styles.css')
]);
 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\UI\Components\Layout\Box;
 
Box::make()->addAssets([
Js::make('/js/custom.js'),
Css::make('/css/styles.css')
]);

При создании компонента

 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\UI\Components\MoonShineComponent;
 
final class MyComponent extends MoonShineComponent
{
/**
* @return list<AssetElementContract>
*/
protected function assets(): array
{
return [
Js::make('/js/custom.js'),
Css::make('/css/styles.css')
];
}
}
 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\UI\Components\MoonShineComponent;
 
final class MyComponent extends MoonShineComponent
{
/**
* @return list<AssetElementContract>
*/
protected function assets(): array
{
return [
Js::make('/js/custom.js'),
Css::make('/css/styles.css')
];
}
}

При создании компонента через AssetManager

 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\UI\Components\MoonShineComponent;
 
final class MyComponent extends MoonShineComponent
{
protected function booted(): void
{
parent::booted();
 
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
}
 namespaces
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\UI\Components\MoonShineComponent;
 
final class MyComponent extends MoonShineComponent
{
protected function booted(): void
{
parent::booted();
 
$this->getAssetManager()
->add(Css::make('/css/app.css'))
->append(Js::make('/js/app.js'));
}
}

Field

То же самое как и у Component, так как Field является компонентом.

Вывод через Blade

<x-moonshine::layout.assets>
@vite([
'resources/css/main.css',
'resources/js/app.js',
], 'vendor/moonshine')
</x-moonshine::layout.assets>
<x-moonshine::layout.assets>
@vite([
'resources/css/main.css',
'resources/js/app.js',
], 'vendor/moonshine')
</x-moonshine::layout.assets>

Собственная сборка

В процессе работы с MoonShine, особенно при использовании подхода через Blade, вам могут потребоваться дополнительные CSS-классы TailwindCSS, которых нет в изначальной сборке MoonShine. Для решения этой задачи подойдет собственная сборка, в которой будет включен MoonShine, и вы сможете собирать билды со своим набором классов и стилей + MoonShine.

Автоматическая публикация

Для автоматической публикации собственной сборки выполните команду:

php artisan moonshine:publish
php artisan moonshine:publish

Выберите Assets Template.

После чего будут опубликованы и заменены следующие файлы:

  • vite.config.js,
  • postcss.config.js,
  • resources/css/app.css.

Для автоматической публикации ассетов необходим TailwindCSS 4+ и Laravel 12+.

Вам останется только добавить ассеты в ваш проект.

Реализация через MoonShineLayout

Необходимо добавить JavaScript MoonShine $this->getMainThemeJs(), а также ассеты вашего приложения, где Css::make(Vite::asset('resources/css/app.css')) также содержит CSS MoonShine.

 namespaces
use Illuminate\Support\Facades\Vite;
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
 
final class MoonShineLayout extends AppLayout
{
protected function assets(): array
{
return [
$this->getMainThemeJs(),
Css::make(Vite::asset('resources/css/app.css')),
Js::make(Vite::asset('resources/js/app.js')),
];
}
}
 namespaces
use Illuminate\Support\Facades\Vite;
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
 
final class MoonShineLayout extends AppLayout
{
protected function assets(): array
{
return [
$this->getMainThemeJs(),
Css::make(Vite::asset('resources/css/app.css')),
Js::make(Vite::asset('resources/js/app.js')),
];
}
}

Реализация через Blade

Необходимо добавить JavaScript MoonShine @vite(['resources/js/app.js'], 'vendor/moonshine'), а также ассеты вашего приложения, где resources/css/app.css также содержит CSS MoonShine.

<x-moonshine::layout.head>
<x-moonshine::layout.assets>
@vite(['resources/js/app.js'], 'vendor/moonshine')
@vite(['resources/css/app.css', 'resources/js/app.js'])
</x-moonshine::layout.assets>
</x-moonshine::layout.head>
<x-moonshine::layout.head>
<x-moonshine::layout.assets>
@vite(['resources/js/app.js'], 'vendor/moonshine')
@vite(['resources/css/app.css', 'resources/js/app.js'])
</x-moonshine::layout.assets>
</x-moonshine::layout.head>

Ручная реализация собственной сборки

vite.config.js

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
 
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
resolve: {
alias: {
'@moonshine-resources': '/vendor/moonshine/moonshine/src/UI/resources',
}
},
});
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
 
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
resolve: {
alias: {
'@moonshine-resources': '/vendor/moonshine/moonshine/src/UI/resources',
}
},
});

Удален плагин tailwindcss():

plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
- tailwindcss()
]
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
- tailwindcss()
]

Добавлен алиас для путей, где находятся ресурсы MoonShine:

resolve: {
alias: {
'@moonshine-resources': '/vendor/moonshine/moonshine/src/UI/resources',
}
}
resolve: {
alias: {
'@moonshine-resources': '/vendor/moonshine/moonshine/src/UI/resources',
}
}

postcss.config.js

Необходимо установить @tailwindcss/postcss и опубликовать postcss.config.js со следующим содержимым:

export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};

resources/css/app.css

Добавьте импорт CSS MoonShine:

@import '../../vendor/moonshine/moonshine/src/UI/resources/css/main.css';
 
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';
@import '../../vendor/moonshine/moonshine/src/UI/resources/css/main.css';
 
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';