PHPackages                             ewk/moonshine-resource-kit - 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. [Admin Panels](/categories/admin)
4. /
5. ewk/moonshine-resource-kit

ActiveLibrary[Admin Panels](/categories/admin)

ewk/moonshine-resource-kit
==========================

Drag &amp; drop sorting and activity toggling toolkit for MoonShine 4 resources.

v0.1.0(4d ago)01MITPHP &gt;=8.3

Since Jul 7Compare

[ Source](https://github.com/einzelwerk/moonshine-resource-kit)[ Packagist](https://packagist.org/packages/ewk/moonshine-resource-kit)[ Docs](https://github.com/einzelwerk/moonshine-resource-kit)[ RSS](/packages/ewk-moonshine-resource-kit/feed)WikiDiscussions Synced today

READMEChangelog (1)Dependencies (16)Versions (2)Used By (0)

MoonShine Resource Kit
======================

[](#moonshine-resource-kit)

Тулкит для ресурсов [MoonShine 4](https://moonshine-laravel.com): drag &amp; drop сортировка и переключатель активности.

Извлечён из паттернов, повторяющихся в реальных проектах: колонка `sort_order` с перетаскиванием строк в админской таблице и флаг `is_active` с переключением по одной записи и массово. Пакет — тонкий клей над встроенными механизмами MoonShine (`reorderable()`-таблицы на SortableJS, `updateOnPreview()` у переключателей): без собственного JS, всё настраивается на уровне модели/ресурса.

Требования
----------

[](#требования)

- PHP 8.3+
- Laravel 12/13
- MoonShine 4.15+

Установка
---------

[](#установка)

```
composer require ewk/moonshine-resource-kit
```

Сервис-провайдер подключается автоматически. При необходимости опубликуйте конфиг и переводы:

```
php artisan vendor:publish --tag=moonshine-resource-kit-config
php artisan vendor:publish --tag=moonshine-resource-kit-lang
```

Сортировка
----------

[](#сортировка)

### Модель

[](#модель)

Добавьте колонку `sort_order` (`$table->unsignedInteger('sort_order')->nullable();`) и трейт:

```
use Ewk\MoonShineResourceKit\Concerns\Sortable;

class Article extends Model
{
    use Sortable;
}
```

Новые записи получают позицию `max + 1` автоматически. Также трейт даёт:

```
Article::query()->orderedBySort()->get();   // ... ->orderedBySortDesc()

$article->moveUp();
$article->moveDown();
$article->moveToStart();
$article->moveToEnd();
$article->moveToPosition(7);
```

Позиции плотные (всегда `1..N`), перемещение дешёвое: один `UPDATE` со сдвигом диапазона плюс один `UPDATE` с установкой позиции — независимо от размера таблицы.

**Своя колонка** — переопределите в модели (глобальный дефолт задаётся в конфиге):

```
public function getSortColumn(): string
{
    return 'position';
}
```

**Групповые последовательности** — независимая сортировка внутри каждой группы (например, блоки внутри страницы):

```
public function getSortGroupColumns(): array
{
    return ['page_id'];
}
```

### Ресурс

[](#ресурс)

```
use Ewk\MoonShineResourceKit\MoonShine\Concerns\WithReorderable;

class ArticleResource extends ModelResource
{
    use WithReorderable;
}
```

Дальше включите drag &amp; drop на индексной странице — либо трейтом страницы:

```
use Ewk\MoonShineResourceKit\MoonShine\Concerns\ReorderableIndex;

class ArticleIndexPage extends IndexPage
{
    use ReorderableIndex;
}
```

либо вручную в `modifyListComponent()`:

```
protected function modifyListComponent(ComponentContract $component): ComponentContract
{
    return $this->getResource()->applyReorderable($component, $this);
}
```

### Пагинация и большие таблицы

[](#пагинация-и-большие-таблицы)

Drag &amp; drop достаёт только до строк текущей страницы — и это нормально: когда таблица отсортирована по колонке сортировки, страница занимает непрерывный срез позиций, и пакет перераспределяет ровно этот срез. Остальные страницы не затрагиваются.

Чтобы переносить записи **между** страницами, добавьте кнопки перемещения на индексную страницу:

```
use Ewk\MoonShineResourceKit\MoonShine\Buttons\ReorderButtons;

protected function buttons(): ListOf
{
    return parent::buttons()->prepend(...ReorderButtons::for($this->getResource()));
}
```

Вы получите «вверх / вниз», «в начало / в конец» и модалку «на позицию». Каждое перемещение — два `UPDATE`, так что решение масштабируется на большие таблицы без перезаписи всех строк.

### Ручка перетаскивания

[](#ручка-перетаскивания)

По умолчанию тянется вся строка. Чтобы перетаскивать только за ручку:

```
use Ewk\MoonShineResourceKit\MoonShine\Fields\SortHandle;

protected function fields(): iterable
{
    return [
        SortHandle::make(),
        ID::make(),
        // ...
    ];
}

protected function reorderableWithHandle(): bool  // на индексной странице с ReorderableIndex
{
    return true;
}
```

### Вложенные таблицы

[](#вложенные-таблицы)

Для таблиц `HasMany`, которые рендерятся внутри формы другого ресурса:

```
HasMany::make('Blocks', resource: BlockResource::class)
    ->modifyTable(app(BlockResource::class)->reorderableTableModifier()),
```

Переключатель активности
------------------------

[](#переключатель-активности)

### Модель

[](#модель-1)

Добавьте boolean-колонку (`$table->boolean('is_active')->default(true);`) и трейт:

```
use Ewk\MoonShineResourceKit\Concerns\Activatable;

class Article extends Model
{
    use Activatable;
}
```

Вы получите `activate()` / `deactivate()` / `toggleActive()` / `isActive()`, скоупы `active()` / `inactive()` и boolean-каст. Чтобы использовать другую колонку, переопределите `getActiveColumn()`.

### Ресурс

[](#ресурс-1)

```
use Ewk\MoonShineResourceKit\MoonShine\Concerns\WithActivatable;

class ArticleResource extends ModelResource
{
    use WithActivatable;
}
```

Переключение прямо из индексной таблицы:

```
use Ewk\MoonShineResourceKit\MoonShine\Fields\ActiveSwitcher;

protected function fields(): iterable
{
    return [
        // ...
        ActiveSwitcher::make('Активность'),
    ];
}
```

Кнопки массовой активации/деактивации:

```
use Ewk\MoonShineResourceKit\MoonShine\Buttons\ActivityButtons;

protected function buttons(): ListOf
{
    return parent::buttons()->prepend(...ActivityButtons::for($this->getResource()));
}
```

### Глобальные скоупы (opt-in)

[](#глобальные-скоупы-opt-in)

`ActiveScope` (скрывает неактивные записи) и `SortOrderScope` (неявная сортировка) поставляются в пакете, но **никогда не регистрируются автоматически** — глобальный скоуп, зависящий от текущего URL, стреляет в ногу в очередях, Octane и artisan. Регистрируйте их там, где ограничение реально нужно:

```
use Ewk\MoonShineResourceKit\Scopes\ActiveScope;

protected static function booted(): void
{
    static::addGlobalScope(new ActiveScope());
}

// обходной путь:
Article::query()->withInactive()->get();
```

### Состояния фабрик

[](#состояния-фабрик)

```
use Ewk\MoonShineResourceKit\Concerns\HasActiveFactoryStates;

class ArticleFactory extends Factory
{
    use HasActiveFactoryStates;
}

ArticleFactory::new()->active()->create();
ArticleFactory::new()->inactive()->create();
ArticleFactory::new()->randomActive()->create();
```

Конфигурация
------------

[](#конфигурация)

`config/moonshine-resource-kit.php`:

КлючПо умолчаниюНазначение`sort_column``sort_order`Глобальный дефолт для трейта Sortable`active_column``is_active`Глобальный дефолт для трейта Activatable`handle_class``msrk-handle`CSS-класс ячейки-ручки перетаскиванияПереопределения на уровне модели (`getSortColumn()`, `getSortGroupColumns()`, `getActiveColumn()`) всегда приоритетнее конфига.

Разработка
----------

[](#разработка)

```
composer test          # arch + unit + feature
composer phpstan       # level max, только src/
composer format        # PHP-CS-Fixer (PER 3.0)
```

Лицензия
--------

[](#лицензия)

[MIT](LICENSE)

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance99

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

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

Unknown

Total

1

Last Release

4d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/408785?v=4)[Eddie Kovsky](/maintainers/EWK)[@ewk](https://github.com/ewk)

---

Tags

laravelsortableadmindrag-and-dropmoonshineactivatablereorderable

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ewk-moonshine-resource-kit/health.svg)

```
[![Health](https://phpackages.com/badges/ewk-moonshine-resource-kit/health.svg)](https://phpackages.com/packages/ewk-moonshine-resource-kit)
```

###  Alternatives

[dcat-plus/laravel-admin

dcat-plus admin

1474.1k10](/packages/dcat-plus-laravel-admin)[arbory/arbory

Administration interface for Laravel

4754.4k3](/packages/arbory-arbory)[printnow/laravel-admin

Dcat admin 永久分叉版 / 支持 Laravel 10-13, PHP 版本限制 &gt;= 8.1（支持 PHP 8.5）

462.6k](/packages/printnow-laravel-admin)

PHPackages © 2026

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