moonshine / twirl
Web sockets for MoonShine for component reload
1.0.0
2025-06-28 22:56 UTC
Requires
- php: ^8.2
Requires (Dev)
- moonshine/moonshine: 3.x-dev
- orchestra/testbench: ^9.0
- phpunit/phpunit: ^12.0
- rector/rector: ^1.0
Conflicts
- moonshine/moonshine: <3.0
README
Install
composer require moonshine/twirl
Quick start
Add Twirl component in your MoonShineLayot
use MoonShine\Twirl\Components\Twirl; Twirl::make(),
Now you can trigger the event and update your component
use MoonShine\Twirl\Events\TwirlEvent; TwirlEvent::dispatch( selector: '.your-selector' . $id, (string) Badge::make(), HtmlReloadAction::OUTER_HTML );
Settings for Centrifugo
Centrifugo backend example
<?php /** * @see https://github.com/centrifugal/phpcent */ declare(strict_types=1); namespace App\Services; use Throwable; use phpcent\Client; use MoonShine\Twirl\DTO\TwirlData; use MoonShine\Twirl\Contracts\TwirlBroadcastContract; final class Centrifugo implements TwirlBroadcastContract { public function send(string $channel, TwirlData $twirlData): void { try { $client = new Client(config('app.centrifugo.host'). '/api', config('app.centrifugo.api-key')); $client->publish($channel, $twirlData->toArray()); } catch (Throwable $e) { report($e); } } }
Add into provider
$this->app->bind(TwirlBroadcastContract::class, Centrifugo::class);
Centrifugo frontend ts example
import { Centrifuge, PublicationContext } from "centrifuge"; import axios from "axios"; declare global { interface Window { MoonShine: { onCallback: (name: string, callback: Function) => void; } } interface ImportMeta { env: { [key: string]: string; } } } document.addEventListener("moonshine:init", async () => { if (! window.MoonShine) { console.error('MoonShine is not initialized'); return; } let token = await getOrCreateToken(); const wsUrl = getWsURL() const centrifuge = new Centrifuge(wsUrl, { token: token }); centrifuge.on('connected', () => { document.dispatchEvent(new CustomEvent('moonshine:twirl')); }).connect(); window.MoonShine.onCallback('onTwirl', function(channel: string, onTwirl: (data: any) => void): void { if(centrifuge.getSubscription(channel) !== null) { return; } const sub = centrifuge.newSubscription(channel); sub.on('publication', function(ctx: PublicationContext): void { onTwirl(ctx.data); }).on('error', (error): void => { console.log(error) }) .subscribe() }); });