Skip to content

Commit 8ba78d8

Browse files
committed
WIP: reimagine Navigation rendering features
This PR concept starts to add ability to register renderers like custom Nav item types. It also implements first-party examples of using the new system with the built-in nav item types.
1 parent 49a6339 commit 8ba78d8

File tree

7 files changed

+250
-39
lines changed

7 files changed

+250
-39
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace LaraZeus\Sky\Classes\LinkRenderers;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class GenericLinkRenderer extends NavLinkRenderer
8+
{
9+
10+
public function getModel(): ?Model
11+
{
12+
return null;
13+
}
14+
15+
public function getLink(): ?string
16+
{
17+
return $this->item['data']['url'];
18+
}
19+
20+
public function isActiveRoute(): bool
21+
{
22+
return false;
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace LaraZeus\Sky\Classes\LinkRenderers;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use LaraZeus\Sky\Models\Library;
7+
use LaraZeus\Sky\SkyPlugin;
8+
9+
class LibraryLinkRenderer extends NavLinkRenderer
10+
{
11+
public static string $renders = 'library-link';
12+
13+
public function getModel(): ?Model
14+
{
15+
return SkyPlugin::get()->getModel('Tag')
16+
::find($this->item['data']['library_id']);
17+
}
18+
19+
public function getLink(): ?string
20+
{
21+
/**
22+
* @var Library $tag
23+
*/
24+
$tag = $this->getModel();
25+
return route('library.tag', $tag->slug);
26+
}
27+
28+
public function isActiveRoute(): bool
29+
{
30+
/**
31+
* @var Library $tag
32+
*/
33+
$tag = $this->getModel();
34+
return str(request()->url())->contains($tag->library->first()->slug);
35+
}
36+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace LaraZeus\Sky\Classes\LinkRenderers;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
abstract class NavLinkRenderer
8+
{
9+
public static string $renders;
10+
11+
public function __construct(
12+
protected array $item
13+
) {}
14+
15+
// TODO: something to control these classes for end-user?
16+
public static string $activeClasses = 'border-b border-b-secondary-500 text-secondary-500';
17+
public static string $defaultActiveClass = 'border-transparent';
18+
19+
abstract public function getModel(): ?Model;
20+
21+
abstract public function getLink(): ?string;
22+
23+
abstract public function isActiveRoute(): bool;
24+
25+
public function getActiveClass(): string
26+
{
27+
return $this->isActiveRoute() ?
28+
self::$activeClasses :
29+
self::$defaultActiveClass;
30+
}
31+
32+
/**
33+
* @return array{}
34+
*/
35+
public function getPreparedLink(string $classes = ''): array {
36+
return [
37+
'classes' => $classes . ' ' . $this->getActiveClass(),
38+
'target' => $this->item['data']['target'] ?? '_self',
39+
'link' => $this->getLink(),
40+
'label' => $this->item['label'],
41+
'wrap' => null,
42+
'wrapClass' => null,
43+
];
44+
}
45+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace LaraZeus\Sky\Classes\LinkRenderers;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use LaraZeus\Sky\Models\Post;
7+
use LaraZeus\Sky\SkyPlugin;
8+
9+
class PageLinkRenderer extends NavLinkRenderer
10+
{
11+
public static string $renders = 'page-link';
12+
13+
public function getModel(): ?Model
14+
{
15+
return SkyPlugin::get()->getModel('Post')::page()
16+
->whereDate('published_at', '<=', now())
17+
->find($this->item['data']['page_id']);
18+
}
19+
20+
public function getLink(): ?string
21+
{
22+
/**
23+
* @var Post $page
24+
*/
25+
$page = $this->getModel();
26+
return route('page', $page);
27+
}
28+
29+
public function isActiveRoute(): bool
30+
{
31+
/**
32+
* @var Post $page
33+
*/
34+
$page = $this->getModel();
35+
return request()->routeIs('page', $page);
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace LaraZeus\Sky\Classes\LinkRenderers;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use LaraZeus\Sky\Models\Post;
7+
use LaraZeus\Sky\SkyPlugin;
8+
9+
class PostLinkRenderer extends NavLinkRenderer
10+
{
11+
public static string $renders = 'post-link';
12+
13+
public function getModel(): ?Model
14+
{
15+
return SkyPlugin::get()->getModel('Post')
16+
::whereDate('published_at', '<=', now())
17+
->find($this->item['data']['post_id']);
18+
}
19+
20+
public function getLink(): ?string
21+
{
22+
/**
23+
* @var Post $post
24+
*/
25+
$post = $this->getModel();
26+
return route('post', $post);
27+
}
28+
29+
public function isActiveRoute(): bool
30+
{
31+
/**
32+
* @var Post $post
33+
*/
34+
$post = $this->getModel();
35+
return request()->routeIs('post', $post);
36+
}
37+
}

src/Classes/RenderNavItem.php

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,52 @@
22

33
namespace LaraZeus\Sky\Classes;
44

5+
use LaraZeus\Sky\Classes\LinkRenderers\GenericLinkRenderer;
6+
use LaraZeus\Sky\Classes\LinkRenderers\NavLinkRenderer;
57
use LaraZeus\Sky\SkyPlugin;
68

79
class RenderNavItem
810
{
9-
public static function render(array $item, string $class = ''): string
10-
{
11-
$color = 'border-b border-b-secondary-500 text-secondary-500';
12-
13-
if ($item['type'] === 'page-link' || $item['type'] === 'page_link') {
14-
$page = SkyPlugin::get()->getModel('Post')::page()->whereDate('published_at', '<=', now())->find($item['data']['page_id']) ?? '';
15-
$activeClass = (request()->routeIs('page', $page)) ? $color : 'border-transparent';
16-
17-
return '<a class="' . $class . ' ' . $activeClass . '"
18-
target="' . ($item['data']['target'] ?? '_self') . '"
19-
href="' . route('page', $page) . '"
11+
/**
12+
* @var class-string<NavLinkRenderer>
13+
*/
14+
public static string $defaultRendererClass = GenericLinkRenderer::class;
15+
16+
private static function anchorLink(
17+
string $classes,
18+
string $target,
19+
string $link,
20+
string $label,
21+
bool $wrap = false,
22+
string $wrapClass = '',
23+
): string {
24+
// TODO: make this component based?
25+
// Then it's probably easier for users to further customize this?
26+
return '<a class="' . $classes . '"
27+
target="' . $target . '"
28+
href="' . $link . '"
2029
>' .
21-
$item['label'] .
22-
'</a>';
23-
} elseif ($item['type'] === 'post-link' || $item['type'] === 'post_link') {
24-
$post = SkyPlugin::get()->getModel('Post')::find($item['data']['post_id']) ?? '';
25-
$activeClass = (request()->routeIs('post', $post)) ? $color : 'border-transparent';
26-
27-
return '<a class="' . $class . ' ' . $activeClass . '"
28-
target="' . ($item['data']['target'] ?? '_self') . '"
29-
href="' . route('post', $post) . '"
30-
>' .
31-
$item['label'] .
32-
'</a>';
33-
} elseif ($item['type'] === 'library-link' || $item['type'] === 'library_link') {
34-
$tag = SkyPlugin::get()->getModel('Tag')::find($item['data']['library_id']) ?? '';
35-
$activeClass = (str(request()->url())->contains($tag->library->first()->slug)) ? $color : 'border-transparent';
36-
37-
return '<a class="' . $class . ' ' . $activeClass . '"
38-
target="' . ($item['data']['target'] ?? '_self') . '"
39-
href="' . route('library.tag', $tag->slug) . '"
40-
>' .
41-
$item['label'] .
42-
'</a>';
30+
$label .
31+
'</a>';
32+
}
4333

34+
public static function render(array $item, string $class = ''): string
35+
{
36+
$itemType = $item['type'];
37+
if (str($itemType)->contains('_')) {
38+
$itemType = str($itemType)->replace('_', '-')->toString();
39+
}
40+
$renderersMap = SkyPlugin::get()->getNavRenderers();
41+
// TODO: make match current behavior with underscore or hyphen
42+
if (array_key_exists($itemType, $renderersMap)) {
43+
$rendererClass = $renderersMap[$itemType];
44+
$renderer = new $rendererClass($item);
4445
} else {
45-
return '<a class="' . $class . '"
46-
target="' . ($item['data']['target'] ?? '_self') . '"
47-
href="' . $item['data']['url'] . '"
48-
>' .
49-
$item['label'] .
50-
'</a>';
46+
$renderer = new static::$defaultRendererClass($item);
5147
}
48+
/**
49+
* @var NavLinkRenderer $renderer
50+
*/
51+
return static::anchorLink(...$renderer->getPreparedLink($class));
5252
}
5353
}

src/Configuration.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
use Filament\Forms\Components\Select;
77
use Filament\Forms\Components\TextInput;
88
use Illuminate\Support\Str;
9+
use LaraZeus\Sky\Classes\LinkRenderers\LibraryLinkRenderer;
10+
use LaraZeus\Sky\Classes\LinkRenderers\NavLinkRenderer;
11+
use LaraZeus\Sky\Classes\LinkRenderers\PageLinkRenderer;
12+
use LaraZeus\Sky\Classes\LinkRenderers\PostLinkRenderer;
913

1014
trait Configuration
1115
{
@@ -55,6 +59,11 @@ trait Configuration
5559

5660
protected array $itemTypes = [];
5761

62+
/**
63+
* @var class-string<NavLinkRenderer>[]
64+
*/
65+
protected array $navRenderers = [];
66+
5867
protected array | Closure $extraFields = [];
5968

6069
public function navigationGroupLabel(Closure | string $lable): static
@@ -279,4 +288,27 @@ public function hideResources(array $resources = []): static
279288

280289
return $this;
281290
}
291+
292+
/**
293+
* @param class-string<NavLinkRenderer> $rendererClass
294+
* @return $this
295+
*/
296+
public function navRenderer(string $rendererClass): static
297+
{
298+
$this->navRenderers[$rendererClass::$renders] = $rendererClass;
299+
300+
return $this;
301+
}
302+
303+
public function getNavRenderers(): array
304+
{
305+
return array_merge(
306+
[
307+
PageLinkRenderer::$renders => PageLinkRenderer::class,
308+
PostLinkRenderer::$renders => PostLinkRenderer::class,
309+
LibraryLinkRenderer::$renders => LibraryLinkRenderer::class,
310+
],
311+
$this->navRenderers
312+
);
313+
}
282314
}

0 commit comments

Comments
 (0)