generated from boboko/starter
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e186fc231 |
+2
-2
@@ -32,7 +32,7 @@
|
|||||||
"Tests\\": "tests/"
|
"Tests\\": "tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"_repositories": [
|
"repositories": [
|
||||||
{
|
{
|
||||||
"type": "path",
|
"type": "path",
|
||||||
"url": "../boboko-core",
|
"url": "../boboko-core",
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"repositories": [
|
"_repositories": [
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://code.radical-elements.com/boboko/core.git"
|
"url": "https://code.radical-elements.com/boboko/core.git"
|
||||||
|
|||||||
Generated
+10
-6
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "a89bc3e4e93372ee52664163d56f783b",
|
"content-hash": "ba9c83a482613f3bd1f9a2b82ab91f66",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "anourvalar/eloquent-serialize",
|
"name": "anourvalar/eloquent-serialize",
|
||||||
@@ -516,10 +516,10 @@
|
|||||||
{
|
{
|
||||||
"name": "boboko/core",
|
"name": "boboko/core",
|
||||||
"version": "0.22.0",
|
"version": "0.22.0",
|
||||||
"source": {
|
"dist": {
|
||||||
"type": "git",
|
"type": "path",
|
||||||
"url": "https://code.radical-elements.com/boboko/core.git",
|
"url": "../boboko-core",
|
||||||
"reference": "985f53efa2d34849f35c8e0f4129f861be762e76"
|
"reference": "547f07f01e043206d36b54290633f9f8fe6c1e14"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
@@ -552,6 +552,7 @@
|
|||||||
"Modules\\Core\\Providers\\AuthServiceProvider",
|
"Modules\\Core\\Providers\\AuthServiceProvider",
|
||||||
"Modules\\Core\\Providers\\CustomerServiceProvider",
|
"Modules\\Core\\Providers\\CustomerServiceProvider",
|
||||||
"Modules\\Core\\Providers\\CheckoutServiceProvider",
|
"Modules\\Core\\Providers\\CheckoutServiceProvider",
|
||||||
|
"Modules\\Core\\Providers\\CheckoutModuleServiceProvider",
|
||||||
"Modules\\Core\\Providers\\PaymentServiceProvider",
|
"Modules\\Core\\Providers\\PaymentServiceProvider",
|
||||||
"Modules\\Core\\Providers\\LocalizationServiceProvider",
|
"Modules\\Core\\Providers\\LocalizationServiceProvider",
|
||||||
"Modules\\Core\\Providers\\CatalogServiceProvider",
|
"Modules\\Core\\Providers\\CatalogServiceProvider",
|
||||||
@@ -570,7 +571,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"description": "Core module — authentication and shared panel behaviour",
|
"description": "Core module — authentication and shared panel behaviour",
|
||||||
"time": "2026-09-25T12:58:41+00:00"
|
"transport-options": {
|
||||||
|
"symlink": true,
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
inside the add-to-cart <form> so their values travel with it as
|
inside the add-to-cart <form> so their values travel with it as
|
||||||
custom_fields[key]. text → input, textarea → textarea, file → photo upload.
|
custom_fields[key]. text → input, textarea → textarea, file → photo upload.
|
||||||
|
|
||||||
|
The label is styled like the product option labels (option-buttons /
|
||||||
|
color-swatch); the optional help_text shows under it. Help text is
|
||||||
|
product-page only; the cart/checkout line meta only snapshots the label.
|
||||||
|
|
||||||
A photo is uploaded as soon as it's picked (custom-field-upload-controller.js)
|
A photo is uploaded as soon as it's picked (custom-field-upload-controller.js)
|
||||||
and only the resulting File row's id (boboko-core's Modules\Core\File\
|
and only the resulting File row's id (boboko-core's Modules\Core\File\
|
||||||
Models\File) is submitted with the form — the file input itself has no
|
Models\File) is submitted with the form — the file input itself has no
|
||||||
@@ -22,18 +26,25 @@
|
|||||||
$id = 'custom-field-'.$field['key'];
|
$id = 'custom-field-'.$field['key'];
|
||||||
$name = 'custom_fields['.$field['key'].']';
|
$name = 'custom_fields['.$field['key'].']';
|
||||||
$required = (bool) ($field['required'] ?? false);
|
$required = (bool) ($field['required'] ?? false);
|
||||||
|
$hint = filled($field['help_text'] ?? null) ? $field['help_text'] : null;
|
||||||
|
// mb-1 on top of the field's gap-2 matches the option labels' mb-3;
|
||||||
|
// with a hint, the label + hint group carries that spacing instead.
|
||||||
|
$labelClass = 'font-bold text-sm uppercase tracking-wide'.($hint ? '' : ' mb-1');
|
||||||
|
$hintId = $hint ? $id.'-hint' : null;
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@switch($field['type'])
|
@switch($field['type'])
|
||||||
@case('textarea')
|
@case('textarea')
|
||||||
<x-ui.field :label="$field['label']" :for="$id" :required="$required">
|
<x-ui.field :label="$field['label']" :label-class="$labelClass" :hint="$hint" :for="$id" :required="$required">
|
||||||
<x-ui.textarea :id="$id" :name="$name" :required="$required" :rows="4" maxlength="2000" />
|
<x-ui.textarea :id="$id" :name="$name" :required="$required" :rows="4" maxlength="2000" :aria-describedby="$hintId" />
|
||||||
</x-ui.field>
|
</x-ui.field>
|
||||||
@break
|
@break
|
||||||
|
|
||||||
@case('file')
|
@case('file')
|
||||||
<x-ui.field
|
<x-ui.field
|
||||||
:label="$field['label']"
|
:label="$field['label']"
|
||||||
|
:label-class="$labelClass"
|
||||||
|
:hint="$hint"
|
||||||
:for="$id"
|
:for="$id"
|
||||||
:required="$required"
|
:required="$required"
|
||||||
:description="__('storefront.product.custom_field_photo_hint', ['size' => CustomFieldUploadController::MAX_KILOBYTES / 1024])"
|
:description="__('storefront.product.custom_field_photo_hint', ['size' => CustomFieldUploadController::MAX_KILOBYTES / 1024])"
|
||||||
@@ -49,7 +60,7 @@
|
|||||||
:id="$id"
|
:id="$id"
|
||||||
:accept="CustomFieldUploadController::accept()"
|
:accept="CustomFieldUploadController::accept()"
|
||||||
:required="$required"
|
:required="$required"
|
||||||
aria-describedby="{{ $id }}-description {{ $id }}-error"
|
aria-describedby="{{ $hintId ? $hintId.' ' : '' }}{{ $id }}-description {{ $id }}-error"
|
||||||
data-custom-field-upload-target="file"
|
data-custom-field-upload-target="file"
|
||||||
data-action="change->custom-field-upload#upload"
|
data-action="change->custom-field-upload#upload"
|
||||||
/>
|
/>
|
||||||
@@ -69,8 +80,8 @@ class="w-24 h-24 object-cover border border-black"
|
|||||||
@break
|
@break
|
||||||
|
|
||||||
@default
|
@default
|
||||||
<x-ui.field :label="$field['label']" :for="$id" :required="$required">
|
<x-ui.field :label="$field['label']" :label-class="$labelClass" :hint="$hint" :for="$id" :required="$required">
|
||||||
<x-ui.input :id="$id" :name="$name" :required="$required" maxlength="255" />
|
<x-ui.input :id="$id" :name="$name" :required="$required" maxlength="255" :aria-describedby="$hintId" />
|
||||||
</x-ui.field>
|
</x-ui.field>
|
||||||
@endswitch
|
@endswitch
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
@props([
|
@props([
|
||||||
'label' => null,
|
'label' => null,
|
||||||
'labelDescription' => null,
|
'labelDescription' => null,
|
||||||
|
'labelClass' => null,
|
||||||
|
'hint' => null,
|
||||||
'for' => null,
|
'for' => null,
|
||||||
'description' => null,
|
'description' => null,
|
||||||
'error' => null,
|
'error' => null,
|
||||||
@@ -10,9 +12,23 @@
|
|||||||
<div {{ $attributes->merge(['class' => 'flex flex-col gap-2']) }}>
|
<div {{ $attributes->merge(['class' => 'flex flex-col gap-2']) }}>
|
||||||
|
|
||||||
@if ($label)
|
@if ($label)
|
||||||
|
{{-- With a hint, label + hint are grouped so the hint sits tight
|
||||||
|
under the label, with the usual gap before the input. The input
|
||||||
|
should reference {for}-hint in its aria-describedby. --}}
|
||||||
|
@if ($hint) <div class="flex flex-col gap-1"> @endif
|
||||||
|
|
||||||
<label
|
<label
|
||||||
@if ($for) for="{{ $for }}" @endif
|
@if ($for) for="{{ $for }}" @endif
|
||||||
|
@if ($labelClass) class="{{ $labelClass }}" @endif
|
||||||
>{{ $label }}@if ($required)<span class="ml-1" aria-hidden="true">*</span>@endif @if ($labelDescription) <span class="text-sm text-neutral-500">({{ $labelDescription }})</span> @endif</label>
|
>{{ $label }}@if ($required)<span class="ml-1" aria-hidden="true">*</span>@endif @if ($labelDescription) <span class="text-sm text-neutral-500">({{ $labelDescription }})</span> @endif</label>
|
||||||
|
|
||||||
|
@if ($hint)
|
||||||
|
<p
|
||||||
|
@if ($for) id="{{ $for }}-hint" @endif
|
||||||
|
class="text-sm text-neutral-500"
|
||||||
|
>{{ $hint }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
|
|||||||
Reference in New Issue
Block a user