feat(theme-settings): agregar configuracion de ancho del contenedor

- Nuevo grupo 'Layout y Contenedor' en theme-settings
- Opciones: 1140px, 1200px, 1320px (default), 1400px, 100%
- CSS dinamico aplicado via ThemeSettingsRenderer
- Corregir selectores de hero en Rail Ads (.hero-section, .featured-image-container)
- Agregar setTimeout para esperar carga de DOM
- Aumentar gap de separacion a 30px
- Subir maxTop al 40% del viewport

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-11-27 21:03:43 -06:00
parent 2fa112ab7f
commit 0dfe3fcd2c
5 changed files with 198 additions and 15 deletions

View File

@@ -24,6 +24,10 @@ final class ThemeSettingsFieldMapper implements FieldMapperInterface
public function getFieldMapping(): array
{
return [
// Layout
'themeSettingsContainerMaxWidth' => ['group' => 'layout', 'attribute' => 'container_max_width'],
'themeSettingsContentColumnWidth' => ['group' => 'layout', 'attribute' => 'content_column_width'],
// Custom Code
'themeSettingsCustomCss' => ['group' => 'custom_code', 'attribute' => 'custom_css'],
'themeSettingsCustomJsHeader' => ['group' => 'custom_code', 'attribute' => 'custom_js_header'],

View File

@@ -27,6 +27,9 @@ final class ThemeSettingsFormBuilder
$html .= $this->buildHeader($componentId);
// Layout Group (nueva seccion)
$html .= $this->buildLayoutGroup($componentId);
$html .= '<div class="row g-3">';
// Columna izquierda - CSS
@@ -44,6 +47,87 @@ final class ThemeSettingsFormBuilder
return $html;
}
private function buildLayoutGroup(string $componentId): string
{
$html = '<div class="card shadow-sm mb-4" style="border-left: 4px solid #FF8600;">';
$html .= ' <div class="card-body">';
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
$html .= ' <i class="bi bi-layout-wtf me-2" style="color: #FF8600;"></i>';
$html .= ' Layout y Contenedor';
$html .= ' </h5>';
$html .= ' <div class="row g-3">';
// Container Max Width
$html .= ' <div class="col-md-6">';
$containerWidth = $this->renderer->getFieldValue($componentId, 'layout', 'container_max_width', '1320');
$containerWidthStr = is_string($containerWidth) ? $containerWidth : '1320';
$html .= $this->buildSelect(
'themeSettingsContainerMaxWidth',
'Ancho maximo del contenedor',
$containerWidthStr,
[
'1140' => '1140px (Bootstrap md)',
'1200' => '1200px (Compacto)',
'1320' => '1320px (Bootstrap xxl - Default)',
'1400' => '1400px (Amplio)',
'100%' => '100% (Fluido)'
],
'Valores menores dejan mas espacio para Rail Ads laterales'
);
$html .= ' </div>';
// Content Column Width
$html .= ' <div class="col-md-6">';
$columnWidth = $this->renderer->getFieldValue($componentId, 'layout', 'content_column_width', 'col-lg-9');
$columnWidthStr = is_string($columnWidth) ? $columnWidth : 'col-lg-9';
$html .= $this->buildSelect(
'themeSettingsContentColumnWidth',
'Ancho columna de contenido',
$columnWidthStr,
[
'col-lg-8' => '8 columnas (66.67%)',
'col-lg-9' => '9 columnas (75% - Default)',
'col-lg-10' => '10 columnas (83.33%)',
'col-lg-12' => '12 columnas (100% sin sidebar)'
],
'Proporcion de la columna principal vs sidebar'
);
$html .= ' </div>';
$html .= ' </div>';
$html .= ' <div class="alert alert-info small mb-0 mt-3">';
$html .= ' <i class="bi bi-info-circle me-1"></i>';
$html .= ' Reduce el ancho del contenedor para dar mas espacio a los Rail Ads en pantallas grandes.';
$html .= ' </div>';
$html .= ' </div>';
$html .= '</div>';
return $html;
}
private function buildSelect(string $id, string $label, string $value, array $options, string $helpText = ''): string
{
$html = ' <div class="mb-3">';
$html .= ' <label for="' . esc_attr($id) . '" class="form-label small mb-1 fw-semibold">';
$html .= ' ' . esc_html($label);
$html .= ' </label>';
$html .= ' <select class="form-select form-select-sm" id="' . esc_attr($id) . '">';
foreach ($options as $optionValue => $optionLabel) {
$selected = ($value === (string) $optionValue) ? ' selected' : '';
$html .= ' <option value="' . esc_attr($optionValue) . '"' . $selected . '>' . esc_html($optionLabel) . '</option>';
}
$html .= ' </select>';
if (!empty($helpText)) {
$html .= ' <div class="form-text small">' . esc_html($helpText) . '</div>';
}
$html .= ' </div>';
return $html;
}
private function buildHeader(string $componentId): string
{
$html = '<div class="rounded p-4 mb-4 shadow text-white" ';