Add alpineJS Support for label field

This commit is contained in:
philipp lang 2024-12-27 00:51:40 +01:00
parent c11dd2b699
commit 6b505e1c02
6 changed files with 73 additions and 12 deletions

View File

@ -27,7 +27,7 @@ class Editor extends Component
return <<<'HTML' return <<<'HTML'
<div class="flex flex-col group {{$heightClass}}"> <div class="flex flex-col group {{$heightClass}}">
@if ($label) @if ($label)
<x-form::label :required="$required">{{$label}}</x-form::label> <x-form::label :required="$required" :value="$label" />
@endif @endif
<div class="relative w-full h-full"> <div class="relative w-full h-full">
@ -41,7 +41,7 @@ class Editor extends Component
@updated="$wire.{{$attributes->wire('model')->value}} = $event.detail" @updated="$wire.{{$attributes->wire('model')->value}} = $event.detail"
x-data="editor($wire.{{$attributes->wire('model')->value}})" x-data="editor($wire.{{$attributes->wire('model')->value}})"
id="{{$id}}" id="{{$id}}"
{{$attributes}} {{$attributes->except(['label', ':label'])}}
></div> ></div>
<x-ui::errors :for="$name" /> <x-ui::errors :for="$name" />
@if($hint) @if($hint)

View File

@ -4,6 +4,7 @@ namespace App\View\Form;
use App\View\Traits\HasFormDimensions; use App\View\Traits\HasFormDimensions;
use Illuminate\View\Component; use Illuminate\View\Component;
use Illuminate\View\ComponentAttributeBag;
class Label extends Component class Label extends Component
{ {
@ -12,17 +13,46 @@ class Label extends Component
public function __construct( public function __construct(
public bool $required = false, public bool $required = false,
public string $value = ''
) { ) {
} }
public function asAlpineString(ComponentAttributeBag $attributes, string $tagName): string
{
$rawTag = ':' . $tagName;
if ($attributes->has($rawTag)) {
return $attributes->get($rawTag);
}
$output = e($this->{$tagName});
return str($output)->swap([
'`' => '\\`',
'$' => '\\$',
'{' => '\\{',
'}' => '\\}',
])->wrap('`');
}
public function asAlpineBool(ComponentAttributeBag $attributes, string $tagName): string
{
$rawTag = ':' . $tagName;
if ($attributes->has($rawTag)) {
return $attributes->get($rawTag);
}
return $this->{$tagName} ? 'true' : 'false';
}
public function render() public function render()
{ {
return <<<'HTML' return <<<'HTML'
<span class="font-semibold leading-none text-gray-400 group-[.size-default]:text-sm group-[.size-sm]:text-xs"> <span class="font-semibold leading-none text-gray-400 group-[.size-default]:text-sm group-[.size-sm]:text-xs">
{{ $slot }} <span x-text="{!! $asAlpineString($attributes, 'value') !!}"></span>
@if ($required) <template x-if="{!! $asAlpineBool($attributes, 'required') !!}">
<span class="text-red-800">&nbsp;*</span> <span class="text-red-800">&nbsp;*</span>
@endif </template>
</span> </span>
HTML; HTML;
} }

View File

@ -29,10 +29,10 @@ class Lever extends Component
return <<<'HTML' return <<<'HTML'
<label class="flex flex-col items-start group {{$heightClass}} " for="{{$id}}" style="{{$heightVars}}"> <label class="flex flex-col items-start group {{$heightClass}} " for="{{$id}}" style="{{$heightVars}}">
@if ($label) @if ($label)
<x-form::label :required="$required">{{$label}}</x-form::label> <x-form::label :required="$required" :value="$label" />
@endif @endif
<span class="relative flex-none flex h-[var(--height)] @if($hint) pr-8 @endif"> <span class="relative flex-none flex h-[var(--height)] @if($hint) pr-8 @endif">
<input id="{{$id}}" type="checkbox" name="{{$name}}" value="{{$value}}" @if($disabled) disabled="disabled" @endif class="absolute peer opacity-0" {{ $attributes }} /> <input id="{{$id}}" type="checkbox" name="{{$name}}" value="{{$value}}" @if($disabled) disabled="disabled" @endif class="absolute peer opacity-0" {{ $attributes->except('label.raw') }} />
<span class="relative cursor-pointer h-full w-[calc(var(--height)*2)] rounded peer-focus:bg-red-500 duration-300 bg-gray-700 peer-checked:bg-primary-700"></span> <span class="relative cursor-pointer h-full w-[calc(var(--height)*2)] rounded peer-focus:bg-red-500 duration-300 bg-gray-700 peer-checked:bg-primary-700"></span>
<span class="absolute h-full top-0 left-0 flex-none flex justify-center items-center aspect-square"> <span class="absolute h-full top-0 left-0 flex-none flex justify-center items-center aspect-square">
<x-ui::sprite <x-ui::sprite

View File

@ -29,11 +29,11 @@ class Select extends Component
return <<<'HTML' return <<<'HTML'
<label class="flex flex-col group {{$heightClass}}" for="{{$id}}" style="{{$heightVars}}"> <label class="flex flex-col group {{$heightClass}}" for="{{$id}}" style="{{$heightVars}}">
@if ($label) @if ($label)
<x-form::label :required="$required">{{$label}}</x-form::label> <x-form::label :required="$required" :value="$label"></x-form::label>
@endif @endif
<div class="relative flex-none flex"> <div class="relative flex-none flex">
<select {{$attributes}} @if($disabled) disabled @endif name="{{$name}}" id="{{$id}}" <select {{$attributes->except(['label', ':label'])}} @if($disabled) disabled @endif name="{{$name}}" id="{{$id}}"
class=" class="
w-full h-[var(--height)] border-gray-600 border-solid text-gray-300 bg-gray-700 leading-none rounded-lg w-full h-[var(--height)] border-gray-600 border-solid text-gray-300 bg-gray-700 leading-none rounded-lg
group-[.size-default]:border-2 group-[.size-sm]:border group-[.size-default]:border-2 group-[.size-sm]:border

View File

@ -28,7 +28,7 @@ class Text extends Component
return <<<'HTML' return <<<'HTML'
<label {{ $attributes->merge(['class' => 'flex flex-col group '.$heightClass])->only('class') }} for="{{$id}}" style="{{$heightVars}}"> <label {{ $attributes->merge(['class' => 'flex flex-col group '.$heightClass])->only('class') }} for="{{$id}}" style="{{$heightVars}}">
@if ($label) @if ($label)
<x-form::label :required="$required">{{$label}}</x-form::label> <x-form::label :required="$required" :value="$label" />
@endif @endif
<div class="relative flex-none flex"> <div class="relative flex-none flex">
<input <input
@ -42,7 +42,7 @@ class Text extends Component
group-[.size-default]:text-sm group-[.size-sm]:text-xs group-[.size-default]:text-sm group-[.size-sm]:text-xs
group-[.size-default]:p-2 group-[.size-sm]:p-1 group-[.size-default]:p-2 group-[.size-sm]:p-1
" "
{{ $attributes->except('class') }} {{ $attributes->except(['class', 'label', ':label']) }}
/> />
<x-ui::errors :for="$name" /> <x-ui::errors :for="$name" />
@if($hint) @if($hint)

View File

@ -0,0 +1,31 @@
<?php
namespace Tests\Unit\View\Form;
use Illuminate\Support\Facades\Blade;
use Tests\TestCase;
uses(TestCase::class);
it('renders component', function ($component, $params, $expected = '', $notExpected = '') {
$rendered = Blade::render($component, $params);
if ($expected) {
expect($rendered)->toContain($expected);
}
if ($notExpected) {
expect($rendered)->not()->toContain($notExpected);
}
})->with([
'component parameter' => ['<x-form::label :value="$label" />', ['label' => 'the label'], 'x-text="`the label`"'],
'component parameter with double quotes' => ['<x-form::label :value="$label" />', ['label' => 'the "label"'], 'x-text="`the &quot;label&quot;`"'],
'component parameter with ``' => ['<x-form::label value="the `label`" />', [], 'x-text="`the \\`label\\``"'],
'escape dollars' => ['<x-form::label value="the $label" />', [], 'x-text="`the \\$label`"'],
'escape kl' => ['<x-form::label value="the {label}" />', [], 'x-text="`the \\{label\\}`"'],
'raw php string' => ['<x-form::label value="the label" />', [], 'x-text="`the label`"'],
'raw js string' => ['<x-form::label ::value="theLabel" />', [], 'x-text="theLabel"'],
'raw js string with tag' => ['<x-form::label ::value="the<Label" />', [], 'x-text="the<Label"'],
'renders required' => ['<x-form::label value="" required/>', [], 'x-if="true"'],
'renders required' => ['<x-form::label value="" />', [], 'x-if="false"'],
]);