mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
77 lines
2.3 KiB
PHP
77 lines
2.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Views\Components;
|
|
|
|
use Exception;
|
|
use Override;
|
|
use ViewComponents\Component;
|
|
|
|
class DropdownMenu extends Component
|
|
{
|
|
protected array $props = ['id', 'labelledby', 'placement', 'offsetX', 'offsetY', 'items'];
|
|
|
|
protected array $casts = [
|
|
'offsetX' => 'number',
|
|
'offsetY' => 'number',
|
|
'items' => 'array',
|
|
];
|
|
|
|
protected string $id;
|
|
|
|
protected string $labelledby;
|
|
|
|
protected string $placement = 'bottom-end';
|
|
|
|
protected int $offsetX = 0;
|
|
|
|
protected int $offsetY = 0;
|
|
|
|
protected array $items = [];
|
|
|
|
public function setItems(string $value): void
|
|
{
|
|
$this->items = json_decode(htmlspecialchars_decode($value), true);
|
|
}
|
|
|
|
#[Override]
|
|
public function render(): string
|
|
{
|
|
if ($this->items === []) {
|
|
throw new Exception('Dropdown menu has no items');
|
|
}
|
|
|
|
$menuItems = '';
|
|
foreach ($this->items as $item) {
|
|
switch ($item['type']) {
|
|
case 'link':
|
|
$menuItems .= anchor($item['uri'], $item['title'], [
|
|
'class' => 'inline-flex gap-x-1 items-center px-4 py-1 hover:bg-highlight' . (array_key_exists('class', $item) ? ' ' . $item['class'] : ''),
|
|
]);
|
|
break;
|
|
case 'html':
|
|
$menuItems .= htmlspecialchars_decode((string) $item['content']);
|
|
break;
|
|
case 'separator':
|
|
$menuItems .= '<hr class="my-2 border border-subtle">';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->mergeClass('absolute flex flex-col py-2 rounded-lg z-60 whitespace-nowrap text-skin-base border-contrast bg-elevated border-3');
|
|
$this->attributes['id'] = $this->id;
|
|
$this->attributes['aria-labelledby'] = $this->labelledby;
|
|
$this->attributes['data-dropdown'] = 'menu';
|
|
$this->attributes['data-dropdown-placement'] = $this->placement;
|
|
$this->attributes['data-dropdown-offset-x'] = $this->offsetX;
|
|
$this->attributes['data-dropdown-offset-y'] = $this->offsetY;
|
|
|
|
return <<<HTML
|
|
<nav {$this->getStringifiedAttributes()}>{$menuItems}</nav>
|
|
HTML;
|
|
}
|
|
}
|