Development
You're browsing the documentation for an old version of MoonShine. Consider upgrading your project to MoonShine 2.x.
-
Sections
MoonShine provides opportunities to extend the basic functionality and write your own packages that improve the features. In this section, we will provide a list of such packages, an example with creating your own field and action.
If you can't figure out how your MoonShine package should look like, we've prepared a ready-made template for you. Package template
The following entities could be extended:
- Fields
- Filters
- Decorations
- Actions
- Metrics
- InputExtension
- FormComponent
- Resource
# Custom field
Here is a small example of creating your own field! It is a visual editor based on the CKEditor js plugin
First, let's create a class that extends the MoonShine fields
namespace App\MoonShine\Fields; use MoonShine\Fields\Field; final class CKEditor extends Field{ protected static string $view = 'fields.ckeditor'; protected array $assets = [ 'https://cdn.ckeditor.com/ckeditor5/35.3.0/super-build/ckeditor.js' ];}
Then, create a view with implementation
<x-moonshine::form.textarea :attributes="$element->attributes()->merge([ 'id' => 'ckeditor_' . $item->getKey() . '_' . $element->id(), 'name' => $element->name() ])">{!! $element->formViewValue($item) ?? '' !!}</x-moonshine::form.textarea> <script> CKEDITOR.ClassicEditor.create(document.getElementById("ckeditor_{{ $item->getKey() }}_{{ $element->id() }}"), { // https://ckeditor.com/docs/ckeditor5/latest/features/toolbar/toolbar.html#extended-toolbar-configuration-format toolbar: { items: [ 'heading', '|', 'bold', 'italic', 'strikethrough', 'underline', 'code', 'subscript', 'superscript', 'removeFormat', '|', 'bulletedList', 'numberedList', 'todoList', 'outdent', 'indent', '|', 'undo', 'redo', '-', 'exportPDF','exportWord', '|', 'findAndReplace', '|', 'fontSize', 'fontColor', 'fontBackgroundColor', 'alignment', '|', 'link', 'insertImage', 'blockQuote', 'insertTable', 'mediaEmbed', 'codeBlock', 'htmlEmbed', '|', 'specialCharacters', 'horizontalLine', 'sourceEditing' ], shouldNotGroupWhenFull: true }, // Changing the language of the interface requires loading the language file using the <script> tag. // language: 'es', list: { properties: { styles: true, startIndex: true, reversed: true } }, // https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#configuration heading: { options: [ { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' }, { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' }, { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' }, { model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' }, { model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' }, { model: 'heading5', view: 'h5', title: 'Heading 5', class: 'ck-heading_heading5' }, { model: 'heading6', view: 'h6', title: 'Heading 6', class: 'ck-heading_heading6' } ] }, // https://ckeditor.com/docs/ckeditor5/latest/features/editor-placeholder.html#using-the-editor-configuration placeholder: 'Welcome to CKEditor 5!', // https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-family-feature fontFamily: { options: [ 'default', 'Arial, Helvetica, sans-serif', 'Courier New, Courier, monospace', 'Georgia, serif', 'Lucida Sans Unicode, Lucida Grande, sans-serif', 'Tahoma, Geneva, sans-serif', 'Times New Roman, Times, serif', 'Trebuchet MS, Helvetica, sans-serif', 'Verdana, Geneva, sans-serif' ], supportAllValues: true }, // https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-size-feature fontSize: { options: [ 10, 12, 14, 'default', 18, 20, 22 ], supportAllValues: true }, // Be careful with the setting below. It instructs CKEditor to accept ALL HTML markup. // https://ckeditor.com/docs/ckeditor5/latest/features/general-html-support.html#enabling-all-html-features htmlSupport: { allow: [ { name: /.*/, attributes: true, classes: true, styles: true } ] }, codeBlock: { languages: [ { language: 'php', label: 'Php' }, { language: 'js', label: 'Js' } ] }, // Be careful with enabling previews // https://ckeditor.com/docs/ckeditor5/latest/features/html-embed.html#content-previews htmlEmbed: { showPreviews: true }, // https://ckeditor.com/docs/ckeditor5/latest/features/link.html#custom-link-attributes-decorators link: { decorators: { addTargetToExternalLinks: true, defaultProtocol: 'https://', toggleDownloadable: { mode: 'manual', label: 'Downloadable', attributes: { download: 'file' } } } }, // https://ckeditor.com/docs/ckeditor5/latest/features/mentions.html#configuration mention: { feeds: [ { marker: '@', feed: [ '@apple', '@bears', '@brownie', '@cake', '@cake', '@candy', '@canes', '@chocolate', '@cookie', '@cotton', '@cream', '@cupcake', '@danish', '@donut', '@dragée', '@fruitcake', '@gingerbread', '@gummi', '@ice', '@jelly-o', '@liquorice', '@macaroon', '@marzipan', '@oat', '@pie', '@plum', '@pudding', '@sesame', '@snaps', '@soufflé', '@sugar', '@sweet', '@topping', '@wafer' ], minimumCharacters: 1 } ] }, simpleUpload: { // The URL that the images are uploaded to. uploadUrl: '{{ route('moonshine.attachments') }}', }, // The "super-build" contains more premium features that require additional configuration, disable them below. // Do not turn them on unless you read the documentation and know how to configure them and setup the editor. removePlugins: [ // These two are commercial, but you can try them out without registering to a trial. // 'ExportPdf', // 'ExportWord', 'CKBox', 'CKFinder', //'EasyImage', // This sample uses the Base64UploadAdapter to handle image uploads as it requires no configuration. // https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/base64-upload-adapter.html // Storing images as Base64 is usually a very bad idea. // Replace it on production website with other solutions: // https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/image-upload.html // 'Base64UploadAdapter', 'RealTimeCollaborativeComments', 'RealTimeCollaborativeTrackChanges', 'RealTimeCollaborativeRevisionHistory', 'PresenceList', 'Comments', 'TrackChanges', 'TrackChangesData', 'RevisionHistory', 'Pagination', 'WProofreader', // Careful, with the Mathtype plugin CKEditor will not load when loading this sample // from a local file system (file://) - load this site via HTTP server if you enable MathType 'MathType' ] });</script> <style> .ck-editor__editable { max-height: 400px; background-color: white!important; color: black!important; }</style>
That's it!
# Custom Action
MoonShine comes with several built-in actions such as Export и Import but you can also create your own custom actions.
To do this, you need to create a class that extends the MoonShine action class and define the handle method.
namespace App\MoonShine\Actions; use MoonShine\Actions\Action; class CustomAction extends Action{ public function handle(): mixed { // Code with the handler logic }}
This is enough to display our custom action on the resource page. However, let's take a look at what else we can define in our action class.
class CustomAction extends Action{ protected static string $view = 'view.custom'; // Custom blade mapping protected bool $withQuery = true; // Whether to pass the entire current getQuery to the action's URL. protected bool $inDropdown = false; // Display the button outside the dropdown menu. protected ?string $icon = 'heroicons.outline.table-cells'; // Icon for the button.}
Next, register the action in the actions method of the resource where you want to display it.
public function actions(): array{ return [ CustomAction::make('Custom Action'), ];}
That's it!