+ @if ($status)
+
{!! $statusLabel !!}
+ @endif
+ @if ($showHeading)
+
+ {!! $headingPrefix !!}{!! $labelElementHtml !!}
+ @if ($static)
+
{!! t('Read Only') !!}
+ @endif
+ @if ($showLabelExtra)
+
+ {!! $actionMenuHtml !!}{!! $attributeCopyHtml !!}{!! $labelExtra !!}
+ @endif
+ {!! $headingSuffix !!}
+
+ @endif
+ @if ($instructionsContent && $instructionsPosition === 'before')
+
{!! $instructionsContent !!}
+ @endif
+
{!! $input !!}
+ @if ($instructionsContent && $instructionsPosition === 'after')
+
{!! $instructionsContent !!}
+ @endif
+ @if ($tipContent)
+ @include('c::forms.field-notice', ['id' => $tipId, 'variant' => 'info', 'icon' => 'lightbulb', 'label' => t('Tip:'), 'content' => $tipContent])
+ @endif
+ @if ($warningContent)
+ @include('c::forms.field-notice', ['id' => $warningId, 'variant' => 'warning', 'icon' => '', 'label' => t('Warning:'), 'content' => $warningContent])
+ @endif
+ {!! $errorListHtml !!}
+
diff --git a/src/Cp/FormFields.php b/src/Cp/FormFields.php
index 04b3fefa8ec..37ff8c3122d 100644
--- a/src/Cp/FormFields.php
+++ b/src/Cp/FormFields.php
@@ -121,13 +121,6 @@ public static function fieldHtml(string|Stringable|callable $input, array $confi
);
$showLabelExtra = $showAttribute || $showActionMenu || isset($config['labelExtra']);
- $instructionsHtml = $instructions
- ? Html::tag('div', app(ContentHtml::class)->parseMarkdown($instructions), [
- 'id' => $instructionsId,
- 'class' => ['instructions'],
- ])
- : '';
-
$translationDescription = $config['translationDescription'] ?? t('This field is translatable.');
$translationIconHtml = Html::button('', [
'class' => ['t9n-indicator', 'prevent-autofocus'],
@@ -165,8 +158,8 @@ public static function fieldHtml(string|Stringable|callable $input, array $confi
$labelHtml = '';
}
- return
- Html::beginTag('div', Arr::merge(
+ return view('c::forms.field', [
+ 'fieldAttributes' => Arr::merge(
[
'class' => $fieldClass,
'id' => $fieldId,
@@ -179,54 +172,45 @@ public static function fieldHtml(string|Stringable|callable $input, array $confi
] + $data,
],
$config['fieldAttributes'] ?? []
- )).
- ($status
- ? Html::beginTag('div', [
- 'id' => $statusId,
- 'class' => ['status-badge', Str::toString($status[0])],
- 'title' => $status[1],
- 'aria-hidden' => 'true',
- ]).
- Html::tag('span', $status[1], [
- 'class' => 'visually-hidden',
- ]).
- Html::endTag('div')
- : '').
- (($label || $showLabelExtra)
- ? (
- Html::beginTag('div', ['class' => 'heading font-bold mb-1']).
- ($config['headingPrefix'] ?? '').
- ($label
- ? Html::tag($fieldset ? 'legend' : 'label', $labelHtml, Arr::merge([
- 'id' => $labelId,
- 'class' => $config['labelClass'] ?? null,
- 'for' => ! $fieldset ? $id : null,
- ], $config['labelAttributes'] ?? []))
- : '').
- ($static ? Html::tag('span', t('Read Only'), [
- 'class' => ['read-only-badge'],
- ]) : '').
- ($showLabelExtra
- ? Html::tag('div', '', ['class' => 'flex-grow']).
- ($showActionMenu ? app(MenuHtml::class)->disclosureMenu($config['actionMenuItems'], [
- 'hiddenLabel' => t('Actions'),
- 'buttonAttributes' => [
- 'class' => ['action-btn', 'small', 'prevent-autofocus'],
- ],
- ]) : '').
- ($showAttribute ? self::renderTemplate('_includes/forms/copytextbtn', [
- 'id' => "$id-attribute",
- 'class' => ['code', 'small', 'light'],
- 'value' => $config['attribute'],
- ]) : '').
- ($config['labelExtra'] ?? '')
- : '').
- ($config['headingSuffix'] ?? '').
- Html::endTag('div')
- )
- : '').
- ($instructionsPosition === 'before' ? $instructionsHtml : '').
- Html::tag('div', $input, Arr::merge(
+ ),
+ 'status' => $status,
+ 'statusId' => $statusId,
+ 'statusClass' => $status ? Str::toString($status[0]) : null,
+ 'statusLabel' => $status ? $status[1] : null,
+ 'showHeading' => $label || $showLabelExtra,
+ 'headingPrefix' => $config['headingPrefix'] ?? null,
+ 'headingSuffix' => $config['headingSuffix'] ?? null,
+ 'labelElementHtml' => $label
+ ? Html::tag($fieldset ? 'legend' : 'label', $labelHtml, Arr::merge([
+ 'id' => $labelId,
+ 'class' => $config['labelClass'] ?? null,
+ 'for' => ! $fieldset ? $id : null,
+ ], $config['labelAttributes'] ?? []))
+ : null,
+ 'static' => $static,
+ 'showLabelExtra' => $showLabelExtra,
+ 'actionMenuHtml' => $showActionMenu
+ ? app(MenuHtml::class)->disclosureMenu($config['actionMenuItems'], [
+ 'hiddenLabel' => t('Actions'),
+ 'buttonAttributes' => [
+ 'class' => ['action-btn', 'small', 'prevent-autofocus'],
+ ],
+ ])
+ : null,
+ 'attributeCopyHtml' => $showAttribute
+ ? self::renderTemplate('_includes/forms/copytextbtn', [
+ 'id' => "$id-attribute",
+ 'class' => ['code', 'small', 'light'],
+ 'value' => $config['attribute'],
+ ])
+ : null,
+ 'labelExtra' => isset($config['labelExtra']) ? (string) $config['labelExtra'] : null,
+ 'instructionsId' => $instructionsId,
+ 'instructionsContent' => $instructions
+ ? app(ContentHtml::class)->parseMarkdown($instructions)
+ : null,
+ 'instructionsPosition' => $instructionsPosition,
+ 'inputContainerAttributes' => Arr::merge(
[
'class' => array_filter([
'input',
@@ -236,43 +220,28 @@ public static function fieldHtml(string|Stringable|callable $input, array $confi
]),
],
$config['inputContainerAttributes'] ?? []
- )).
- ($instructionsPosition === 'after' ? $instructionsHtml : '').
- self::noticeHtml($tipId, 'notice', t('Tip:'), $tip).
- self::noticeHtml($warningId, 'warning', t('Warning:'), $warning).
- ($errors
+ ),
+ 'input' => $input,
+ 'tipId' => $tipId,
+ 'tipContent' => self::noticeContent($tip),
+ 'warningId' => $warningId,
+ 'warningContent' => self::noticeContent($warning),
+ 'errorListHtml' => $errors
? self::renderTemplate('_includes/forms/errorList', [
'id' => $errorsId,
'errors' => $errors,
])
- : '').
- Html::endTag('div');
+ : null,
+ ])->render();
}
- private static function noticeHtml(string $id, string $class, string $label, string|Stringable|null $message): string
+ private static function noticeContent(string|Stringable|null $message): ?string
{
if (! $message) {
- return '';
+ return null;
}
- $message = (string) $message;
-
- return
- Html::beginTag('p', [
- 'id' => $id,
- 'class' => [$class, 'has-icon'],
- ]).
- Html::tag('span', '', [
- 'class' => 'icon',
- 'aria' => [
- 'hidden' => 'true',
- ],
- ]).
- Html::tag('span', "$label ", [
- 'class' => 'visually-hidden',
- ]).
- Html::tag('span', Html::decodeDoubles(Markdown::parseParagraph(Html::encodeInvalidTags($message)))).
- Html::endTag('p');
+ return Html::decodeDoubles(Markdown::parseParagraph(Html::encodeInvalidTags((string) $message)));
}
public static function buttonHtml(array $config): string
diff --git a/src/Cp/Html/FieldHtml.php b/src/Cp/Html/FieldHtml.php
new file mode 100644
index 00000000000..9d2e95fd3f4
--- /dev/null
+++ b/src/Cp/Html/FieldHtml.php
@@ -0,0 +1,126 @@
+contentHtml->metadataHtml([
+ t('ID') => $field->id,
+ t('Used by') => fn () => $this->usagesHtml($field),
+ ]);
+ }
+
+ private function usagesHtml(FieldInterface $field): string
+ {
+ $layouts = $this->fields->findFieldUsages($field);
+
+ if ($layouts->isEmpty()) {
+ return Html::tag('i', t('No usages'));
+ }
+
+ /** @var FieldLayout[][] $layoutsByType */
+ $layoutsByType = $layouts
+ ->keyBy('uid')
+ ->groupBy(fn (FieldLayout $layout) => $layout->type ?? '__UNKNOWN__')
+ ->all();
+
+ /** @var FieldLayout[] $unknownLayouts */
+ $unknownLayouts = Arr::pull($layoutsByType, '__UNKNOWN__');
+ /** @var FieldLayout[] $layoutsWithProviders */
+ $layoutsWithProviders = [];
+
+ // re-fetch as many of these as we can from the element types,
+ // so they have a chance to supply the layout providers
+ foreach ($layoutsByType as $type => &$typeLayouts) {
+ /** @var class-string