Skip to content

Commit

Permalink
support enums for descriptions and icons
Browse files Browse the repository at this point in the history
  • Loading branch information
199ocero committed Jan 4, 2024
1 parent d65beae commit 9c6fa27
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 84 deletions.
152 changes: 75 additions & 77 deletions resources/views/forms/components/radio-deck.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
@php
use Filament\Support\Enums\IconPosition;
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\IconSize;
$id = $getId();
$isDisabled = $isDisabled();
$statePath = $getStatePath();
Expand All @@ -12,86 +16,80 @@
$shouldOptionBeDisabled = $isDisabled || $isOptionDisabled($value, $label);
@endphp

<x-filament::input.wrapper>
<label class="flex cursor-pointer gap-x-3">
<input @disabled($shouldOptionBeDisabled) id="{{ $id }}-{{ $value }}"
name="{{ $id }}" type="radio" value="{{ $value }}" wire:loading.attr="disabled"
{{ $applyStateBindingModifiers('wire:model') }}="{{ $statePath }}"
{{ $getExtraInputAttributeBag()->class(['peer hidden']) }} />
<label class="flex cursor-pointer gap-x-3">
<input @disabled($shouldOptionBeDisabled) id="{{ $id }}-{{ $value }}"
name="{{ $id }}" type="radio" value="{{ $value }}" wire:loading.attr="disabled"
{{ $applyStateBindingModifiers('wire:model') }}="{{ $statePath }}"
{{ $getExtraInputAttributeBag()->class(['peer hidden']) }} />

@php
$iconExists = $hasIcons($value);
$iconPosition = $getIconPosition();
$alignment = $getAlignment();
$color = $getColor();
$icon = $getIcon($value);
$iconSize = $getIconSize();
$descriptionExists = $hasDescription($value);
$description = $getDescription($value);
@endphp
<div @class([
'flex px-4 py-2 w-full text-sm leading-6 rounded-lg gap-5',
$iconExists
? match ($iconPosition) {
\Filament\Support\Enums\IconPosition::Before,
'before'
=> 'justify-start',
\Filament\Support\Enums\IconPosition::After,
'after'
=> 'justify-between flex-row-reverse',
default => 'justify-start',
}
: 'justify-start',
match ($alignment) {
\Filament\Support\Enums\Alignment::Center, 'center' => 'items-center',
\Filament\Support\Enums\Alignment::Start, 'start' => 'items-start',
\Filament\Support\Enums\Alignment::End, 'end' => 'items-end',
default => 'items-center',
},
'ring-1 ring-gray-200 dark:ring-gray-700 peer-checked:ring-2',
'peer-disabled:bg-gray-100/50 dark:peer-disabled:bg-gray-700/50 peer-disabled:cursor-not-allowed',
match ($color) {
'gray' => 'peer-checked:ring-gray-600 dark:peer-checked:ring-gray-700',
default
=> 'fi-color-custom peer-checked:ring-custom-600 dark:peer-checked:ring-custom-700',
},
]) @style([
\Filament\Support\get_color_css_variables($color, shades: [600, 700]) => $color !== 'gray',
])>
@if ($iconExists)
<x-filament::icon :icon="$icon" @class([
'flex-shrink-0',
match ($iconSize) {
\Filament\Support\Enums\IconSize::Small => 'h-8 w-8',
'sm' => 'h-8 w-8',
\Filament\Support\Enums\IconSize::Medium => 'h-9 w-9',
'md' => 'h-9 w-9',
\Filament\Support\Enums\IconSize::Large => 'h-10 w-10',
'lg' => 'h-10 w-10',
default => 'h-8 w-8',
},
match ($color) {
'gray' => 'fi-color-gray text-gray-600 dark:text-gray-500',
default => 'fi-color-custom text-custom-600 dark:text-custom-500',
},
]) @style([
\Filament\Support\get_color_css_variables($color, shades: [600, 500]) => $color !== 'gray',
]) />
@endif
<div class="place-items-start">
<span class="font-medium text-gray-950 dark:text-white">
{{ $label }}
</span>
@php
$iconExists = $hasIcons($value);
$iconPosition = $getIconPosition();
$alignment = $getAlignment();
$color = $getColor();
$icon = $getIcon($value);
$iconSize = $getIconSize();
$descriptionExists = $hasDescription($value);
$description = $getDescription($value);
@endphp
<div @class([
'flex px-4 py-2 w-full text-sm leading-6 rounded-lg gap-5 bg-white dark:bg-gray-900',
$iconExists
? match ($iconPosition) {
IconPosition::Before, 'before' => 'justify-start',
IconPosition::After, 'after' => 'justify-between flex-row-reverse',
default => 'justify-start',
}
: 'justify-start',
match ($alignment) {
Alignment::Center, 'center' => 'items-center',
Alignment::Start, 'start' => 'items-start',
Alignment::End, 'end' => 'items-end',
default => 'items-center',
},
'ring-1 ring-gray-200 dark:ring-gray-700 peer-checked:ring-2',
'peer-disabled:bg-gray-100/50 dark:peer-disabled:bg-gray-700/50 peer-disabled:cursor-not-allowed',
match ($color) {
'gray' => 'peer-checked:ring-gray-600 dark:peer-checked:ring-gray-700',
default
=> 'fi-color-custom peer-checked:ring-custom-600 dark:peer-checked:ring-custom-700',
},
]) @style([
\Filament\Support\get_color_css_variables($color, shades: [600, 700]) => $color !== 'gray',
])>
@if ($iconExists)
<x-filament::icon :icon="$icon" @class([
'flex-shrink-0',
match ($iconSize) {
IconSize::Small => 'h-8 w-8',
'sm' => 'h-8 w-8',
IconSize::Medium => 'h-9 w-9',
'md' => 'h-9 w-9',
IconSize::Large => 'h-10 w-10',
'lg' => 'h-10 w-10',
default => 'h-8 w-8',
},
match ($color) {
'gray' => 'fi-color-gray text-gray-600 dark:text-gray-500',
default => 'fi-color-custom text-custom-600 dark:text-custom-500',
},
]) @style([
\Filament\Support\get_color_css_variables($color, shades: [600, 500]) => $color !== 'gray',
]) />
@endif
<div class="place-items-start">
<span class="font-medium text-gray-950 dark:text-white">
{{ $label }}
</span>

@if ($descriptionExists)
<p class="text-gray-500 dark:text-gray-400">
{{ $description }}
</p>
@endif
</div>
@if ($descriptionExists)
<p class="text-gray-500 dark:text-gray-400">
{{ $description }}
</p>
@endif
</div>
</label>
</x-filament::input.wrapper>
</div>
</label>
@endforeach
</x-filament::grid>
</x-dynamic-component>
8 changes: 8 additions & 0 deletions src/Contracts/HasDescriptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace JaOcero\RadioDeck\Contracts;

interface HasDescriptions
{
public function getDescriptions(): ?string;
}
8 changes: 8 additions & 0 deletions src/Contracts/HasIcons.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace JaOcero\RadioDeck\Contracts;

interface HasIcons
{
public function getIcons(): ?string;
}
83 changes: 76 additions & 7 deletions src/Forms/Components/RadioDeck.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,46 @@

use Closure;
use Filament\Forms\Components\Radio;
use Filament\Support\Concerns\HasAlignment;
use Filament\Support\Concerns\HasColor;
use Filament\Support\Concerns\HasIcon;
use Filament\Support\Concerns\HasColor;
use Filament\Support\Concerns\HasAlignment;
use Illuminate\Contracts\Support\Arrayable;
use JaOcero\RadioDeck\Contracts\HasDescriptions;
use JaOcero\RadioDeck\Contracts\HasIcons;
use JaOcero\RadioDeck\Intermediary\IntermediaryRadio;

class RadioDeck extends Radio
class RadioDeck extends IntermediaryRadio
{
use HasAlignment;
use HasColor;
use HasIcon;

protected array|Closure|null $icons = null;
protected array | Arrayable | string | Closure | null $icons = null;

protected array | Arrayable | string | Closure $descriptions = [];

protected string $view = 'radio-deck::forms.components.radio-deck';

public function icons(array|Closure|null $icons): static
public function icons(array | Arrayable | string | Closure | null $icons): static
{
$this->icons = $icons;

return $this;
}

public function descriptions(array | Arrayable | string | Closure $descriptions): static
{
$this->descriptions = $descriptions;

return $this;
}

/**
* @param array-key $value
*/
public function hasIcons($value): bool
{
if ($value !== null && ! empty($this->getIcons())) {
if ($value !== null && !empty($this->getIcons())) {
return array_key_exists($value, $this->getIcons());
}

Expand All @@ -42,11 +55,67 @@ public function hasIcons($value): bool
*/
public function getIcons(): mixed
{
return $this->evaluate($this->icons);
$icons = $this->evaluate($this->icons);

$enum = $icons;

if (is_string($enum) && enum_exists($enum)) {
if (is_a($enum, HasIcons::class, allow_string: true)) {
return collect($enum::cases())
->mapWithKeys(fn ($case) => [
($case?->value ?? $case->name) => $case->getIcons() ?? $case->name,
])
->all();
}

return collect($enum::cases())
->mapWithKeys(fn ($case) => [
($case?->value ?? $case->name) => $case->name,
])
->all();
}

if ($icons instanceof Arrayable) {
$icons = $icons->toArray();
}

return $icons;
}

public function getIcon($value): ?string
{
return $this->getIcons()[$value] ?? null;
}

/**
* @return array<string | Htmlable>
*/
public function getDescriptions(): array
{
$descriptions = $this->evaluate($this->descriptions);

$enum = $descriptions;

if (is_string($enum) && enum_exists($enum)) {
if (is_a($enum, HasDescriptions::class, allow_string: true)) {
return collect($enum::cases())
->mapWithKeys(fn ($case) => [
($case?->value ?? $case->name) => $case->getDescriptions() ?? $case->name,
])
->all();
}

return collect($enum::cases())
->mapWithKeys(fn ($case) => [
($case?->value ?? $case->name) => $case->name,
])
->all();
}

if ($descriptions instanceof Arrayable) {
$descriptions = $descriptions->toArray();
}

return $descriptions;
}
}
79 changes: 79 additions & 0 deletions src/Intermediary/IntermediaryRadio.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace JaOcero\RadioDeck\Intermediary;

use Closure;

use Filament\Forms\Components\Field;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\Support\Arrayable;
use Filament\Forms\Components\Concerns\HasOptions;
use Filament\Forms\Components\Concerns\HasGridDirection;
use Filament\Forms\Components\Concerns\CanFixIndistinctState;
use Filament\Forms\Components\Concerns\HasExtraInputAttributes;
use Filament\Forms\Components\Concerns\CanDisableOptions as ConcernCanDisableOptions;
use Filament\Forms\Components\Contracts\CanDisableOptions as ContractsCanDisableOptions;
use Filament\Forms\Components\Concerns\CanDisableOptionsWhenSelectedInSiblingRepeaterItems;

class IntermediaryRadio extends Field implements ContractsCanDisableOptions
{
use ConcernCanDisableOptions;
use CanDisableOptionsWhenSelectedInSiblingRepeaterItems;
use CanFixIndistinctState;
use HasExtraInputAttributes;
use HasGridDirection;
use HasOptions;

protected array | string | Arrayable | Closure $descriptions = [];

/**
* @param array<string | Htmlable> | Arrayable | string | Closure $descriptions
*/
public function descriptions(array | Arrayable | string | Closure $descriptions): static
{
$this->descriptions = $descriptions;

return $this;
}

/**
* @param array-key $value
*/
public function hasDescription($value): bool
{
return array_key_exists($value, $this->getDescriptions());
}

/**
* @param array-key $value
*/
public function getDescription($value): string | Htmlable | null
{
return $this->getDescriptions()[$value] ?? null;
}

/**
* @return array<string | Htmlable>
*/
public function getDescriptions(): array
{
$descriptions = $this->evaluate($this->descriptions);

if ($descriptions instanceof Arrayable) {
$descriptions = $descriptions->toArray();
}

return $descriptions;
}

public function getDefaultState(): mixed
{
$state = parent::getDefaultState();

if (is_bool($state)) {
return $state ? 1 : 0;
}

return $state;
}
}

0 comments on commit 9c6fa27

Please sign in to comment.