98 lines
3.6 KiB
PHP
98 lines
3.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Pcm\BadgeBundle\Twig\Component;
|
|
|
|
use Pcm\BadgeBundle\Enum\BadgeColour;
|
|
use Pcm\BadgeBundle\Interface\BadgeableInterface;
|
|
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
|
|
use TailwindMerge\TailwindMerge;
|
|
|
|
#[AsTwigComponent(name: 'Pcm:Badge', template: '@PcmBadge/Badge.html.twig')]
|
|
final class Badge
|
|
{
|
|
public string $finalClasses;
|
|
public ?string $label = null;
|
|
public ?string $icon = null;
|
|
|
|
public function __construct(private string $baseClasses)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @param ?BadgeableInterface $obj The object to be converted into a badge
|
|
* @param ?string $class Extra classes to add to the badge element.
|
|
* These will override the base classes in case
|
|
* of conflicts.
|
|
* @param ?string $colour Manually specify the colour of a badge
|
|
* @param bool $outline Whether the badge should be rendered with an outline
|
|
* @param ?string $icon
|
|
*/
|
|
public function mount(?BadgeableInterface $obj = null, ?string $class = null, ?string $colour = null, ?string $label = null, bool $outline = false, ?string $icon = null, bool $glossy = false): void
|
|
{
|
|
if ($outline && $glossy) {
|
|
throw new \RuntimeException('The "outline" and "glossy" props cannot be used together.');
|
|
}
|
|
|
|
if (!$icon) {
|
|
$this->icon = null;
|
|
} else if ("1" === $icon) {
|
|
if (null === $obj) {
|
|
throw new \RuntimeException("Missing icon name.");
|
|
}
|
|
|
|
$this->icon = $obj->getBadgeIcon();
|
|
|
|
if (null === $this->icon) {
|
|
throw new \RuntimeException("Missing icon name.");
|
|
}
|
|
} else {
|
|
$this->icon = $icon;
|
|
}
|
|
|
|
$this->label = $label;
|
|
|
|
if (!$obj && !$colour) {
|
|
throw new \RuntimeException(sprintf('You must specify either a colour an instance of "%s".', BadgeableInterface::class));
|
|
}
|
|
|
|
if ($obj && $colour) {
|
|
throw new \RuntimeException(sprintf('You have specified both the colour "%s" and an instance of "%s". Please use one or the other.', $colour, $obj::class));
|
|
}
|
|
|
|
if ($obj) {
|
|
$palette = $obj->getBadgeColour()->getPalette();
|
|
}
|
|
|
|
if ($colour) {
|
|
$cases = array_map(fn (BadgeColour $b) => strtolower($b->name), BadgeColour::cases());
|
|
|
|
if (!in_array($colour, $cases)) {
|
|
$formattedCases = implode(', ', array_map(fn (string $s) => '"'.$s.'"', $cases));
|
|
throw new \RuntimeException(sprintf('"%s" is not a valid badge colour. Available options are: %s.', $colour, $formattedCases));
|
|
}
|
|
|
|
$colour = strtoupper($colour);
|
|
$palette = BadgeColour::{$colour}->getPalette();
|
|
}
|
|
|
|
$merger = TailwindMerge::instance();
|
|
|
|
if (true === $outline) {
|
|
$classes = sprintf('bg-white %s %s %s %s', $palette->borderColourClass, $palette->textColourClass, $this->baseClasses, $class);
|
|
} else {
|
|
$glossyClass = $glossy ? 'bg-origin-border bg-[image:radial-gradient(ellipse_at_-10%_-50%,rgba(255,255,255,0.35),transparent_70%),linear-gradient(to_bottom,rgba(255,255,255,0.05),rgba(0,0,0,0.12))]' : '';
|
|
|
|
$classes = sprintf('text-white %s %s %s [border-color:transparent] %s', $palette->backgroundColourClass, $glossyClass, $this->baseClasses, $class);
|
|
}
|
|
|
|
if ($this->icon !== null) {
|
|
$classes = sprintf("flex gap-1 items-center %s", $classes);
|
|
}
|
|
|
|
$this->finalClasses = $merger->merge(trim($classes));
|
|
}
|
|
}
|
|
|