Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimagine Navigation rendering features #199

Open
wants to merge 11 commits into
base: 3.x
Choose a base branch
from
7 changes: 7 additions & 0 deletions config/zeus-sky.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,11 @@
* \LaraZeus\Sky\Editors\RichEditor::class,
*/
'editor' => \LaraZeus\Sky\Editors\RichEditor::class,

/**
* A list of custom NavLinkRenderer classes for your app.
*/
'navRenderers' => [
// Add your custom Nav Renderers here...
],
];
3 changes: 3 additions & 0 deletions resources/views/components/sky-link.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<a {{ $attributes->except(['label', 'hasLabelWrap']) }}>
{{ $label }}
</a>
23 changes: 23 additions & 0 deletions src/Classes/LinkRenderers/GenericLinkRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace LaraZeus\Sky\Classes\LinkRenderers;

use Illuminate\Database\Eloquent\Model;

class GenericLinkRenderer extends NavLinkRenderer
{
public function getModel(): ?Model
atmonshi marked this conversation as resolved.
Show resolved Hide resolved
{
return null;
}

public function getLink(): ?string
{
return $this->item['data']['url'];
}

public function isActiveRoute(): bool
{
return false;
}
}
37 changes: 37 additions & 0 deletions src/Classes/LinkRenderers/LibraryLinkRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace LaraZeus\Sky\Classes\LinkRenderers;

use Illuminate\Database\Eloquent\Model;
use LaraZeus\Sky\Models\Library;
use LaraZeus\Sky\SkyPlugin;

class LibraryLinkRenderer extends NavLinkRenderer
{
public static string $rendersKey = 'library-link';

public function getModel(): ?Model
atmonshi marked this conversation as resolved.
Show resolved Hide resolved
{
return SkyPlugin::get()->getModel('Tag')::find($this->item['data']['library_id']);
}

public function getLink(): ?string
{
/**
* @var Library $tag
*/
$tag = $this->getModel();

return route('library.tag', $tag->slug);
}

public function isActiveRoute(): bool
{
/**
* @var Library $tag
*/
$tag = $this->getModel();

return str(request()->url())->contains($tag->library->first()->slug);
}
}
45 changes: 45 additions & 0 deletions src/Classes/LinkRenderers/NavLinkRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace LaraZeus\Sky\Classes\LinkRenderers;

use Illuminate\Database\Eloquent\Model;

abstract class NavLinkRenderer
{
public static string $rendersKey;

public function __construct(
protected array $item
) {
}

public static string $activeClasses = 'border-b border-b-secondary-500 text-secondary-500';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned - having something to control this could be nice, tho not necessary immediately.


public static string $nonActiveClasses = 'border-transparent';

abstract public function getModel(): ?Model;

abstract public function getLink(): ?string;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this one was made nullable on accident 🤔 - technically the most "empty" thing we need out of this is an empty string. Don't think it actually needs to be able to be null?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a use case come to mind, I did use it in on project but for the love of god cant find which one was...

the menu can have nested items, for a dropdown menu with sub nav, so maybe in this case the link can be null!


abstract public function isActiveRoute(): bool;

public function getActiveClass(): string
{
return $this->isActiveRoute() ?
self::$activeClasses :
self::$nonActiveClasses;
}

/**
* @return array{}
*/
public function getPreparedLink(string $classes = ''): array
{
return [
'class' => $classes . ' ' . $this->getActiveClass(),
'target' => $this->item['data']['target'] ?? '_self',
'href' => $this->getLink(),
'label' => $this->item['label'],
];
}
}
39 changes: 39 additions & 0 deletions src/Classes/LinkRenderers/PageLinkRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace LaraZeus\Sky\Classes\LinkRenderers;

use Illuminate\Database\Eloquent\Model;
use LaraZeus\Sky\Models\Post;
use LaraZeus\Sky\SkyPlugin;

class PageLinkRenderer extends NavLinkRenderer
{
public static string $rendersKey = 'page-link';

public function getModel(): ?Model
{
return SkyPlugin::get()->getModel('Post')::page()
->whereDate('published_at', '<=', now())
->find($this->item['data']['page_id']);
}

public function getLink(): ?string
{
/**
* @var Post $page
*/
$page = $this->getModel();

return route('page', $page);
}

public function isActiveRoute(): bool
{
/**
* @var Post $page
*/
$page = $this->getModel();

return request()->routeIs('page', $page);
}
}
38 changes: 38 additions & 0 deletions src/Classes/LinkRenderers/PostLinkRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace LaraZeus\Sky\Classes\LinkRenderers;

use Illuminate\Database\Eloquent\Model;
use LaraZeus\Sky\Models\Post;
use LaraZeus\Sky\SkyPlugin;

class PostLinkRenderer extends NavLinkRenderer
{
public static string $rendersKey = 'post-link';

public function getModel(): ?Model
{
return SkyPlugin::get()->getModel('Post')::whereDate('published_at', '<=', now())
->find($this->item['data']['post_id']);
}

public function getLink(): ?string
{
/**
* @var Post $post
*/
$post = $this->getModel();

return route('post', $post);
}

public function isActiveRoute(): bool
{
/**
* @var Post $post
*/
$post = $this->getModel();

return request()->routeIs('post', $post);
}
}
107 changes: 67 additions & 40 deletions src/Classes/RenderNavItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,79 @@

namespace LaraZeus\Sky\Classes;

use LaraZeus\Sky\SkyPlugin;
use Illuminate\Support\Facades\Blade;
use LaraZeus\Sky\Classes\LinkRenderers\GenericLinkRenderer;
use LaraZeus\Sky\Classes\LinkRenderers\LibraryLinkRenderer;
use LaraZeus\Sky\Classes\LinkRenderers\NavLinkRenderer;
use LaraZeus\Sky\Classes\LinkRenderers\PageLinkRenderer;
use LaraZeus\Sky\Classes\LinkRenderers\PostLinkRenderer;

class RenderNavItem
{
public static function render(array $item, string $class = ''): string
/**
* @var class-string<NavLinkRenderer>
*/
public static string $defaultRendererClass = GenericLinkRenderer::class;

/**
* Set the default active CSS class(es) on a nav link.
*
* @return $this
*/
public static function setActiveClasses(string $activeClasses): void
{
NavLinkRenderer::$activeClasses = $activeClasses;
}

/**
* Set the default non-active CSS class(es) on a nav link.
*
* @return $this
*/
public static function setNonActiveClasses(string $nonActiveClass): void
{
NavLinkRenderer::$nonActiveClasses = $nonActiveClass;
}

public static function getNavRenderers(): array
{
$color = 'border-b border-b-secondary-500 text-secondary-500';

if ($item['type'] === 'page-link' || $item['type'] === 'page_link') {
$page = SkyPlugin::get()->getModel('Post')::page()->whereDate('published_at', '<=', now())->find($item['data']['page_id']) ?? '';
$activeClass = (request()->routeIs('page', $page)) ? $color : 'border-transparent';

return '<a class="' . $class . ' ' . $activeClass . '"
target="' . ($item['data']['target'] ?? '_self') . '"
href="' . route('page', $page) . '"
>' .
$item['label'] .
'</a>';
} elseif ($item['type'] === 'post-link' || $item['type'] === 'post_link') {
$post = SkyPlugin::get()->getModel('Post')::find($item['data']['post_id']) ?? '';
$activeClass = (request()->routeIs('post', $post)) ? $color : 'border-transparent';

return '<a class="' . $class . ' ' . $activeClass . '"
target="' . ($item['data']['target'] ?? '_self') . '"
href="' . route('post', $post) . '"
>' .
$item['label'] .
'</a>';
} elseif ($item['type'] === 'library-link' || $item['type'] === 'library_link') {
$tag = SkyPlugin::get()->getModel('Tag')::find($item['data']['library_id']) ?? '';
$activeClass = (str(request()->url())->contains($tag->library->first()->slug)) ? $color : 'border-transparent';

return '<a class="' . $class . ' ' . $activeClass . '"
target="' . ($item['data']['target'] ?? '_self') . '"
href="' . route('library.tag', $tag->slug) . '"
>' .
$item['label'] .
'</a>';
$allRenderers = array_merge([
PageLinkRenderer::$rendersKey => PageLinkRenderer::class,
PostLinkRenderer::$rendersKey => PostLinkRenderer::class,
LibraryLinkRenderer::$rendersKey => LibraryLinkRenderer::class,
], config('zeus-sky.navRenderers', []));

$renderersMap = [];
foreach ($allRenderers as $renderer) {
/**
* @var NavLinkRenderer $renderer
*/
$renderersMap[$renderer::$rendersKey] = $renderer;
}

return $renderersMap;
}

public static function render(array $item, string $class = ''): string
{
$itemType = $item['type'];
if (str($itemType)->contains('_')) {
$itemType = str($itemType)->replace('_', '-')->toString();
}
$renderersMap = static::getNavRenderers();
if (array_key_exists($itemType, $renderersMap)) {
$rendererClass = $renderersMap[$itemType];
$renderer = new $rendererClass($item);
} else {
return '<a class="' . $class . '"
target="' . ($item['data']['target'] ?? '_self') . '"
href="' . $item['data']['url'] . '"
>' .
$item['label'] .
'</a>';
$renderer = new static::$defaultRendererClass($item);
}

/**
* @var NavLinkRenderer $renderer
*/
return Blade::render(
'<x-zeus::sky-link :class="$class" :target="$target" :href="$href" :label="$label" />',
$renderer->getPreparedLink($class)
);
}
}
22 changes: 22 additions & 0 deletions src/Components/SkyLink.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace LaraZeus\Sky\Components;

use Illuminate\View\Component;

class SkyLink extends Component
{
public function __construct(
public string $label,
public ?bool $hasLabelWrap = false,
) {
}

/**
* {@inheritDoc}
*/
public function render()
{
return view('zeus.sky-link', $this->data());
}
}
6 changes: 6 additions & 0 deletions src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Illuminate\Support\Str;
use LaraZeus\Sky\Classes\LinkRenderers\NavLinkRenderer;

trait Configuration
{
Expand Down Expand Up @@ -55,6 +56,11 @@ trait Configuration

protected array $itemTypes = [];

/**
* @var class-string<NavLinkRenderer>[]
*/
protected array $navRenderers = [];

protected array | Closure $extraFields = [];

public function navigationGroupLabel(Closure | string $lable): static
Expand Down
2 changes: 2 additions & 0 deletions src/SkyServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use LaraZeus\Core\CoreServiceProvider;
use LaraZeus\Sky\Components\SkyLink;
use LaraZeus\Sky\Console\InstallCommand;
use LaraZeus\Sky\Console\migrateCommand;
use LaraZeus\Sky\Console\PublishCommand;
Expand All @@ -31,6 +32,7 @@ public function configurePackage(Package $package): void
->hasConfigFile()
->hasCommands($this->getCommands())
->hasViews('zeus')
->hasViewComponent('zeus', SkyLink::class)
->hasRoute('web');
}

Expand Down