Skip to content

Commit

Permalink
Merge pull request #219 from ejgandelaberon/master
Browse files Browse the repository at this point in the history
feat: Allow passing view and livewire components to layout builder
  • Loading branch information
yajra authored May 18, 2024
2 parents 1c8b2a0 + 86d04fc commit 18d68b6
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 45 deletions.
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
"larastan/larastan": "^2.9.1",
"orchestra/testbench": "^9",
"laravel/pint": "^1.14",
"rector/rector": "^1.0"
"rector/rector": "^1.0",
"livewire/livewire": "^3.4"
},
"suggest": {
"laravel/livewire": "Required for Livewire layout support."
},
"autoload": {
"psr-4": {
Expand Down
21 changes: 19 additions & 2 deletions src/Html/Enums/LayoutPosition.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,25 @@

namespace Yajra\DataTables\Html\Enums;

use Illuminate\Support\Str;

enum LayoutPosition: string
{
case Start = 'Start';
case End = 'End';
case Top = 'top';
case TopStart = 'topStart';
case TopEnd = 'topEnd';
case Bottom = 'bottom';
case BottomStart = 'bottomStart';
case BottomEnd = 'bottomEnd';

public function withOrder(?int $order): string
{
if ($order && $order > 0) {
$parts = Str::of($this->value)->ucsplit();

return $parts->shift().$order.$parts->first();
}

return $this->value;
}
}
123 changes: 89 additions & 34 deletions src/Html/Layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@

namespace Yajra\DataTables\Html;

use Illuminate\Contracts\Support\Renderable;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Fluent;
use Illuminate\Support\Traits\Macroable;
use Illuminate\View\Component;
use InvalidArgumentException;
use Livewire\Livewire;
use Throwable;
use Yajra\DataTables\Html\Enums\LayoutPosition;

class Layout extends Fluent
Expand All @@ -17,79 +23,128 @@ public static function make(array $options = []): static
return new static($options);
}

public function topStart(string|array|null $options, int $order = 0): static
public function top(array|string|null $options, ?int $order = null): static
{
return $this->top($options, $order, LayoutPosition::Start);
$this->attributes[LayoutPosition::Top->withOrder($order)] = $options;

return $this;
}

public function top(array|string|null $options, ?int $order = null, ?LayoutPosition $position = null): static
public function topStart(string|array|null $options, ?int $order = null): static
{
if ($order > 0) {
$this->attributes["top{$order}{$position?->value}"] = $options;
} else {
$this->attributes["top{$position?->value}"] = $options;
}
$this->attributes[LayoutPosition::TopStart->withOrder($order)] = $options;

return $this;
}

public function topEnd(string|array|null $options, int $order = 0): static
public function topEnd(string|array|null $options, ?int $order = null): static
{
return $this->top($options, $order, LayoutPosition::End);
$this->attributes[LayoutPosition::TopEnd->withOrder($order)] = $options;

return $this;
}

public function topEndView(string $selector, int $order = 0): static
public function topView(string $selector, ?int $order = null): static
{
return $this->topView($selector, $order, LayoutPosition::End);
return $this->top($this->renderCustomElement($selector), $order);
}

public function topView(string $selector, int $order = 0, ?LayoutPosition $position = null): static
public function topStartView(string $selector, ?int $order = null): static
{
$script = "function() { return $('{$selector}').html(); }";
return $this->topStart($this->renderCustomElement($selector), $order);
}

return $this->top($script, $order, $position);
public function topEndView(string $selector, ?int $order = null): static
{
return $this->topEnd($this->renderCustomElement($selector), $order);
}

public function bottomStartView(string $selector, int $order = 0): static
public function bottom(array|string|null $options, ?int $order = null): static
{
return $this->bottomView($selector, $order, LayoutPosition::Start);
$this->attributes[LayoutPosition::Bottom->withOrder($order)] = $options;

return $this;
}

public function bottomView(string $selector, int $order = 0, ?LayoutPosition $position = null): static
public function bottomStart(string|array|null $options, ?int $order = null): static
{
$script = "function() { return $('{$selector}').html(); }";
$this->attributes[LayoutPosition::BottomStart->withOrder($order)] = $options;

return $this->bottom($script, $order, $position);
return $this;
}

public function bottom(array|string|null $options, ?int $order = null, ?LayoutPosition $position = null): static
public function bottomEnd(string|array|null $options, ?int $order = null): static
{
if ($order > 0) {
$this->attributes["bottom{$order}{$position?->value}"] = $options;
} else {
$this->attributes["bottom{$position?->value}"] = $options;
}
$this->attributes[LayoutPosition::BottomEnd->withOrder($order)] = $options;

return $this;
}

public function bottomEndView(string $selector, int $order = 0): static
public function bottomView(string $selector, ?int $order = null): static
{
return $this->bottomView($selector, $order, LayoutPosition::End);
return $this->bottom($this->renderCustomElement($selector), $order);
}

public function topStartView(string $selector, int $order = 0): static
public function bottomStartView(string $selector, ?int $order = null): static
{
return $this->topView($selector, $order, LayoutPosition::Start);
return $this->bottomStart($this->renderCustomElement($selector), $order);
}

public function bottomStart(string|array|null $options, int $order = 0): static
public function bottomEndView(string $selector, ?int $order = null): static
{
return $this->bottom($options, $order, LayoutPosition::Start);
return $this->bottomEnd($this->renderCustomElement($selector), $order);
}

/**
* @throws Throwable
*/
public function addView(
Component|Renderable|string $view,
LayoutPosition $layoutPosition,
?int $order = null
): static {
if ($view instanceof Component) {
$view = Blade::renderComponent($view);
}

$html = $view instanceof Renderable ? $view->render() : Blade::render($view);

$element = json_encode($html);

if ($element === false) {
throw new InvalidArgumentException("Cannot render view [$html] to json.");
}

$this->attributes[$layoutPosition->withOrder($order)] = $this->renderCustomElement($element, false);

return $this;
}

public function bottomEnd(string|array|null $options, int $order = 0): static
/**
* @param class-string $component
*
* @throws Throwable
*/
public function addLivewire(
string $component,
LayoutPosition $layoutPosition,
?int $order = null
): static {
$html = json_encode(Livewire::mount($component));

if ($html === false) {
throw new InvalidArgumentException("Cannot render Livewire component [$component] to json.");
}

$this->attributes[$layoutPosition->withOrder($order)] = $this->renderCustomElement($html, false);

return $this;
}

private function renderCustomElement(string $element, bool $asJsSelector = true): string
{
return $this->bottom($options, $order, LayoutPosition::End);
$html = $asJsSelector ? "$('{$element}').html()" : $element;

return "function() { return $html; }";
}
}
Loading

0 comments on commit 18d68b6

Please sign in to comment.