components([ TextInput::make('title') ->required() ->live(onBlur: true) ->afterStateUpdated(function ($state, $set): void { $set('slug', Str::slug((string) $state)); }), TextInput::make('slug') ->required() ->dehydrated() ->readOnly(), Textarea::make('description') ->columnSpanFull(), SpatieMediaLibraryFileUpload::make('featured_image') ->collection('featured-image') ->image() ->imageEditor() ->disk('public') ->visibility('public') ->columnSpanFull() ->hintAction( Action::make('featured_picker') ->label('Pick from Gallery') ->icon('heroicon-m-photo') ->schema([ Select::make('image_id') ->label('Select an existing image') ->allowHtml() ->options(function () { return Media::latest() ->get() ->mapWithKeys(function (Media $item) { $url = $item->getUrl(); $fileName = e($item->file_name); $name = e($item->name ?? ''); $html = "
". "\"{$fileName}\"/". "{$name} — {$fileName}
"; return [$item->id => $html]; })->toArray(); }) ->searchable() ->required(), ]) ->action(function (array $data, SpatieMediaLibraryFileUpload $component) { $record = $component->getRecord(); if (!$record) { \Filament\Notifications\Notification::make() ->warning() ->title('Save the entry first') ->send(); return; } if ($mediaItem = Media::find($data['image_id'])) { // Clear existing featured image $record->clearMediaCollection('featured-image'); // Download from the full URL and add as new media $fullUrl = url($mediaItem->getUrl()); $newMedia = $record->addMediaFromUrl($fullUrl) ->usingName($mediaItem->name ?: $mediaItem->file_name) ->usingFileName($mediaItem->file_name) ->toMediaCollection('featured-image', 'public'); // Update component state $component->state([$newMedia->uuid]); \Filament\Notifications\Notification::make() ->success() ->title('Featured image set') ->send(); } }) ), Toggle::make('is_published') ->required(), Toggle::make('is_featured') ->required(), DatePicker::make('published_at'), RichEditor::make('content') ->columnSpanFull() ->hintAction( Action::make('picker') ->label('Gallery Picker') ->icon('heroicon-m-photo') ->schema([ Select::make('image_url') ->label('Select an existing image') ->allowHtml() ->options(function () { // We must 'get' the collection first so we can call getUrl() // because 'url' is not a column in the Spatie database table. return Media::latest() ->get() ->mapWithKeys(function (Media $item) { $url = $item->getUrl(); $fileName = e($item->file_name); $name = e($item->name ?? ''); $html = "
". "\"{$fileName}\"/". "{$name} — {$fileName}
"; return [$url => $html]; })->toArray(); }) ->searchable() ->required(), ]) ->action(function (array $data, RichEditor $component) { // We dispatch the URL to the browser to be inserted into TipTap $component->getLivewire()->dispatch('insert-editor-content', [ 'statePath' => $component->getStatePath(), 'html' => "", ]); }) ), ]); } }