laraberg icon indicating copy to clipboard operation
laraberg copied to clipboard

Livewire integration and custom colors

Open Jacotheron opened this issue 1 year ago • 1 comments

For Livewire integration, I just need to know, how do I extract the result from Laraberg, to set the livewire property to the correct value? I have tried a couple of things but it just did not want to work.

Then I have also went through a lot of code to see how the colors should be defined, and found the following (passed the following example inside the options object):

colors:[
    {color: '#ffffff', name: "White", slug: 'white'},
    {color: '#000000', name: "Black", slug: 'black'},
    {color: '#ff0000', name: 'Red', slug: 'red'},
    {color: '#00ff00', name: 'Green', slug: 'green'},
    {color: '#0000ff', name: 'Blue', slug: 'blue'},
],

This gives the colors for the highlight function (but working only for background and not foreground), but not to overlays and other areas where we might like a background. I have even tried passing other options to perhaps get a color picker, but this did not do anything useful:

customTextColor: true,
customBackgroundColor: true,
customGradient: true,

Jacotheron avatar Jul 19 '22 09:07 Jacotheron

Ok, I am ready to report back after many days spent on this (as well as looking for different page builders, but found none that fit my needs).

I compiled a developer friendly version of the source (>15MB js file) to see what is happening and how do I use this in the way I need to.

Colors:

Colors are an array of Color objects, each with "name", "slug" and "color" properties. Name is shown when you hover over the color selector; color is used to fill the color selector; slug is used to construct a class string which is added to the element (thus you need to already provide CSS rules for these classes).

Since they need to be on the page with the editor and any page showing the editor output, it is best to configure these globally (I opted for defining them in my config/app.php file as an array of arrays):

'colors' => [
        [
            'name' => 'White',
            'slug' => 'white',
            'color' => '#ffffff',
        ],
        ....
]

This allows me to easily loop through them and generate the classes:

<style>
        @foreach(config('app.colors') as $color)
                .has-{{ $color['slug'] }}-color {
                    color: {!! $color['color'] !!};
                }
                .has-{{ $color['slug'] }}-background-color {
                    background-color: {!! $color['color'] !!};
                }
        @endforeach
</style>

And finally pass it to the editor: colors: @json(config('app.colors'))

Should I change the colors, it will reflect everywhere with no further intervention. Since these colors are passed directly to the color property of the rule, anything you can provide should work: rgb(), rgba(), #hex, #hexa, variables etc.

Custom Colors:

The correct way to enable custom colors (for example useful for the overlay color of images), simply pass disableCustomColors: false to the settings when you define the editor.

Gradients:

Gradients work similar to the colors, hoever they contain a "gradient" property in stead of the "color" property. Once again, you need to provide the CSS Rules, this time with a class constructed as follows: .has-{{ $gradient['slug'] }}-gradient-background

I was however unable to get the gradient palette to show up. May need further investigating.

The custom gradients (which can be defined on the fly), can be enabled with disableCustomGradients: false, - this does work, however I find it frustrating to use.

Font Sizes and Other Flags:

Font sizes work the same as the above (array of arrays, with "size" property, requires css classes etc).

Passed to the editor with fontSizes:

Once again custom font sizes can be enabled: disableCustomFontSizes: false Also custom line heights: enableCustomLineHeight: true Custom Units: enableCustomUnits: true Custom Spacing (Padding): enableCustomSpacing: true Allow editing of code: codeEditingEnabled: true Locking of blocks: canLockBlocks: true Allow aligning wide: alignWide: true

Using with Livewire

I have managed to get this working with Livewire (this works like wire:model.defer since we don't want to send a request on every single change to the content).

Firstly I created a new Blade component, php artisan make:component LarabergEditor with the following contents:

LarabergEditor.php:

<?php
namespace App\View\Components;
use Illuminate\View\Component;
class LarabergEditor extends Component
{
    public $content;
    public $id = '';
    public $wiremodel = false;

    public function __construct($content = '', $id = 'page', $wiremodel = false)
    {
        $this->content = $content; //current content or empty 
        $this->id = $id; //the field ID, is referenced internally
        $this->wiremodel = $wiremodel; //the value of the wire:model property (which will hold the content)
    }

    public function render()
    {
        return view('components.laraberg-editor');
    }
}

laraberg-editor.blade.php:

@push('after-styles')
    <link rel="stylesheet" href="{{asset('vendor/laraberg/css/laraberg.css')}}">
    <link rel="stylesheet" href="{{ asset('vendor/file-manager/css/file-manager.css') }}">
@endpush
@push('before-scripts')
    <script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
@endpush
@push('after-scripts')
    <script src="{{ asset('vendor/laraberg/js/laraberg.js') }}"></script>
    <script src="{{ asset('vendor/laraberg/js/laravel-filemanager/index.js') }}"></script>
    <script>
        jQuery(document).ready(function(){
            const mediaUpload = ({filesList, onFileChange}) => {}
            Laraberg.init('{{ $id }}', {
                mediaUpload,
                alignWide: true,
                imageEditing: true,
                canLockBlocks: false,
                disableCustomColors: false,
                disableCustomGradients: true,
                disableCustomFontSizes: false,
                enableCustomLineHeight: true,
                enableCustomUnits: true,
                enableCustomSpacing: true,
                codeEditingEnabled: true,
                colors: @json(config('app.colors')),
                {{--gradients: @json(config('app.gradients')),--}}
                fontSizes: @json(config('app.fontSizes')),
            });
            @if($wiremodel)
                $('#{{ $id }}').change(function(e) {
                    var editor = $('#{{ $id }}')[0];
                    var content = editor.innerText;
                    @this.set('{{ $wiremodel }}', content, true); // true here means the request is deferred
                });
            @endif
        });

    </script>
@endpush
<div class="bg-white text-black" wire:ignore>
    <textarea id="{{ $id }}" {{ $attributes->merge([]) }} hidden>{{ $content }}</textarea>
</div>

Note the use of @push/@endpush - my template have these sections setup with the @stack() directives. In short the styles should go at the top, and scripts at the bottom.

I have also integrated a media uploader: "unisharp/laravel-filemanager". The lines referencing the vendor/file-manager/css/filemanager.css style, vendor/laraberg/js/laravel-filemanager/index.js script and const mediaUpload = ({filesList, onFileChange}) => {} are all related to the Media Uploader. For convenience I have included them here (and the vendor/laraberg/js/laravel-filemanager/index.js script is in my zip pacakge).

I can then use the editor within a standard form or within a livewire component: <x-laraberg-editor :content="$page->page_content" id="page_content" wiremodel="page_content" />

Other information:

In my testing I have found that having a developer friendly version will be a great help, in addition to the minified version. As such I have compiled it and it can be found in the zip package.

While looking through everything I found an issue where blocks like "columns" etc was unable to get a background color assigned to them. Through lots of digging I concluded that in order to get it to work, I had to modify a couple of lines in the @wordpress/block-editor/build-module/components/use-setting/index.js file (added these lines to const deprecatedFlags):

  'color.link': settings => settings.colors === undefined ? undefined : settings.colors,
  'color.text': settings => settings.colors === undefined ? undefined : settings.colors,
  'color.background': settings => settings.colors === undefined ? undefined : settings.colors,
  'color.palette': settings => settings.colors === undefined ? undefined : settings.colors,
  'color.palette.theme': settings => settings.colors === undefined ? undefined : settings.colors,
  'color.palette.default': settings => settings.colors === undefined ? undefined : settings.colors,

After adding these lines I compiled and now I am able to set background and text colors to most blocks.

For convenience I have this change also in my zip package for anyone to use.

laraberg.zip

The Zip package thus contains the following:

  • css/laraberg.css - minified stylesheet, with its map
  • css/laraberg.dev.css - non minified stylesheet, with its map
  • img/placeholder.jpg - image placeholder
  • js/laraberg.js - minified js, with its map. Above change applied.
  • js/laraberg.dev.js - non minified js, with its map. Above change applied.
  • js/laravel-filemanager/index.js - LaravelFileManager class integrating Laraberg with Laravel Filemanager (not minified)

To use, simply place its contents in the public/vendor/laraberg folder (replacing the existing files that was placed there with the publishing) and reference the needed files (the laraberg.css and laraberg.js files are exactly where they should be; if you need the filemanager capability, also reference that file).

Jacotheron avatar Sep 07 '22 09:09 Jacotheron

This issue has been automatically marked as stale because it has been open for 60 days with no activity.

github-actions[bot] avatar Nov 06 '22 15:11 github-actions[bot]

@Jacotheron Thank you so much. I'm also integrating with livewire and this helped me. I am creating a plugin for Filament (tall kit).

Can you show me an example in which format I should register font size and gradient?

ArtMin96 avatar Jan 09 '23 21:01 ArtMin96

@Jacotheron Your zip file is a great help, I believe that all users would much appreciate if you could do a PR of your code.

elievischel avatar Aug 24 '23 14:08 elievischel