FASE 1 COMPLETADA: Limpieza de defaults hardcodeados

Eliminados todos los componentes incorrectos y defaults duplicados
preparando el sistema para la implementación correcta con tabla de BD.

ARCHIVOS ELIMINADOS (11 archivos):
- admin/assets/js/component-navbar.js
- admin/assets/css/component-navbar.css
- admin/components/component-top-bar.php
- admin/components/component-navbar.php
- admin/components/component-hero-section.php
- admin/components/component-lets-talk-button.php
- admin/includes/sanitizers/class-topbar-sanitizer.php
- admin/includes/sanitizers/class-navbar-sanitizer.php
- admin/includes/sanitizers/class-herosection-sanitizer.php
- admin/includes/sanitizers/class-letstalkbutton-sanitizer.php
- template-parts/navbar-configurable.php

ARCHIVOS MODIFICADOS (6 archivos):
- admin/includes/class-admin-menu.php: Eliminados enqueues de componentes
- admin/includes/class-settings-manager.php: Limpiados get_defaults() y sanitize_settings()
- admin/includes/class-validator.php: Eliminado validate_top_bar()
- admin/pages/main.php: Reducido de 521 a 37 líneas (93%)
- admin/assets/js/admin-app.js: Reducido de 431 a 219 líneas (49%)
- header.php: Eliminado código de Top Bar (92 líneas)

BASE DE DATOS:
- Eliminada opción 'apus_theme_settings' de wp_options

RESUMEN:
- 11 archivos eliminados
- 6 archivos limpiados
- 1 opción de BD eliminada
- Todos los defaults hardcodeados eliminados
- Sistema preparado para FASE 2 (crear tabla de defaults)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-11-13 22:13:23 -06:00
parent 0038ad502c
commit 4818d90386
18 changed files with 25 additions and 4050 deletions

1
.gitignore vendored
View File

@@ -69,3 +69,4 @@ _planeacion/
.playwright-mcp/
.serena/
.claude/
nul

View File

@@ -1,292 +0,0 @@
/* ========================================
ADMIN PANEL - NAVBAR COMPONENT STYLES
Estilos compactos para el panel de administración
======================================== */
/* Sobrescribir estilos del contenedor tab-content */
.tab-content {
padding: 24px 12px !important;
background-color: transparent !important;
}
/* Títulos de sección compactos */
.section-title-compact {
font-size: 1rem;
font-weight: 700;
color: var(--color-navy-primary);
margin-bottom: 0.75rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid var(--color-neutral-100);
}
.section-title-compact i {
margin-right: 0.5rem;
}
/* Fix conflicto con WordPress: Sobreescribir max-width de .card */
body .card,
.apus-admin .card {
max-width: none !important;
}
/* Fix conflicto con WordPress: Sobreescribir estilos de checkbox para que funcionen los switches de Bootstrap */
.form-switch .form-check-input[type="checkbox"] {
width: 2em !important;
height: 1em !important;
border-radius: 2em !important;
background-color: var(--bs-form-check-bg) !important;
background-image: var(--bs-form-switch-bg) !important;
background-position: left center !important;
background-size: contain !important;
background-repeat: no-repeat !important;
margin-left: -2.5em !important;
box-shadow: none !important;
}
.form-switch .form-check-input[type="checkbox"]:checked {
background-color: #0d6efd !important;
border-color: #0d6efd !important;
background-position: right center !important;
background-size: contain !important;
background-repeat: no-repeat !important;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e") !important;
}
body .form-switch .form-check-input[type="checkbox"]::before,
.apus-admin .form-switch .form-check-input[type="checkbox"]::before {
content: none !important;
display: none !important;
background-image: none !important;
width: 0 !important;
height: 0 !important;
}
body .form-switch .form-check-input[type="checkbox"]::after,
.apus-admin .form-switch .form-check-input[type="checkbox"]::after {
content: none !important;
display: none !important;
}
/* Cards compactos */
#navbarTab .card {
border: 1px solid #dee2e6 !important;
border-left: 4px solid #1e3a5f !important;
border-radius: 6px !important;
box-shadow: rgba(0, 0, 0, 0.075) 0px 2px 4px 0px !important;
transition: all 0.3s ease !important;
background-color: #ffffff !important;
padding: 0 !important;
margin: 0 0 16px !important;
}
.form-section.card {
border: 2px solid #d1d5db !important;
border-radius: 12px !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08) !important;
transition: all 0.3s ease;
}
.form-section.card:hover {
border-color: #FF8600 !important;
box-shadow: 0 4px 16px rgba(255, 134, 0, 0.15) !important;
}
.form-section.card .card-body.p-3 {
padding: 1.25rem !important;
}
/* Color pickers compactos */
.form-control-color-compact {
width: 100%;
height: 40px;
border-radius: 0.375rem;
border: 1px solid var(--color-neutral-100);
cursor: pointer;
transition: border-color 0.3s ease;
}
.form-control-color-compact:hover {
border-color: var(--color-orange-primary);
}
/* Form controls pequeños con mejor UX */
#navbarTab .form-control-sm,
#navbarTab .form-select-sm {
font-size: 14px !important;
padding: 6px 12px !important;
border: 1px solid rgb(222, 226, 230) !important;
border-radius: 4px !important;
color: rgb(33, 37, 41) !important;
}
.form-control-sm,
.form-select-sm {
font-size: 0.875rem;
padding: 0.375rem 0.75rem;
}
/* Labels compactos */
.form-label.small {
font-size: 0.875rem;
font-weight: 600;
color: var(--color-neutral-700);
margin-bottom: 0.25rem;
}
/* Fix alineación vertical de labels en switches */
#navbarTab .form-check.form-switch {
display: flex !important;
align-items: center !important;
}
#navbarTab .form-switch .form-check-input {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
#navbarTab .form-switch .form-check-label,
.form-switch .form-check-label.small {
line-height: 16px !important;
padding-top: 0 !important;
margin-top: 0 !important;
margin-bottom: 0 !important;
}
/* Switches más compactos */
.form-check-switch .form-check-input {
width: 2.5rem;
height: 1.25rem;
}
/* Reducir gaps globales */
.row.g-3 {
--bs-gutter-x: 1rem;
--bs-gutter-y: 1rem;
}
.row.g-2 {
--bs-gutter-x: 0.5rem;
--bs-gutter-y: 0.5rem;
}
/* Badges pequeños */
.badge {
font-size: 0.7rem;
padding: 0.2em 0.5em;
vertical-align: middle;
}
/* Tab header compacto */
.tab-header {
background: linear-gradient(135deg, #0E2337 0%, #1a3a5c 100%);
border-radius: 12px;
padding: 1.5rem;
border: 2px solid #FF8600;
box-shadow: 0 4px 12px rgba(14, 35, 55, 0.15);
}
.tab-header h3 {
font-size: 1.4rem;
margin-bottom: 0.25rem;
color: #ffffff;
font-weight: 700;
}
.tab-header p {
color: rgba(255, 255, 255, 0.85);
}
/* Header específico del Navbar Tab */
#navbarTab > .rounded {
background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%) !important;
border-left: 4px solid #FF8600 !important;
border-radius: 6px !important;
padding: 24px !important;
margin-bottom: 24px !important;
box-shadow: rgba(0, 0, 0, 0.15) 0px 8px 16px 0px !important;
}
#navbarTab > .rounded h3 {
font-size: 1.5rem !important;
margin-bottom: 0.25rem !important;
color: #ffffff !important;
font-weight: 700 !important;
}
#navbarTab > .rounded p {
color: rgba(255, 255, 255, 0.85) !important;
margin-bottom: 0 !important;
}
/* Card body padding */
#navbarTab .card-body {
padding: 1rem !important;
}
/* Progress bar pequeña */
.progress[style*="height: 3px"] {
border-radius: 2px;
background-color: var(--color-neutral-100);
}
/* Botones pequeños */
.btn-sm {
font-size: 0.875rem;
padding: 0.375rem 0.75rem;
}
/* Botón primario con estilo de marca */
.btn-primary {
background-color: var(--color-orange-primary);
border-color: var(--color-orange-primary);
font-weight: 600;
}
.btn-primary:hover {
background-color: var(--color-orange-hover);
border-color: var(--color-orange-hover);
}
/* Clases de utilidad de colores */
.text-navy-primary {
color: var(--color-navy-primary);
}
.text-orange-primary {
color: var(--color-orange-primary);
}
.text-neutral-600 {
color: var(--color-neutral-600);
}
.border-neutral-200 {
border-color: #dee2e6 !important;
}
/* Responsive: Mobile First */
@media (max-width: 991px) {
.tab-header {
padding: 0.75rem;
}
.tab-header h3 {
font-size: 1.1rem;
}
.form-section.card .card-body.p-3 {
padding: 0.75rem !important;
}
}
@media (max-width: 576px) {
.tab-header .d-flex {
flex-direction: column;
align-items: flex-start !important;
}
.tab-header button {
width: 100%;
margin-top: 0.5rem;
}
}

View File

@@ -30,14 +30,18 @@ const AdminPanel = {
*/
bindEvents() {
// Botón guardar
document.getElementById('saveSettings').addEventListener('click', () => {
this.saveSettings();
});
const saveBtn = document.getElementById('saveSettings');
if (saveBtn) {
saveBtn.addEventListener('click', () => {
this.saveSettings();
});
}
// Detectar cambios en formularios
const enableSaveButton = () => {
this.STATE.hasChanges = true;
document.getElementById('saveSettings').disabled = false;
const btn = document.getElementById('saveSettings');
if (btn) btn.disabled = false;
};
document.querySelectorAll('input, select, textarea').forEach(input => {
@@ -55,145 +59,6 @@ const AdminPanel = {
this.switchTab(tab);
});
});
// Contador de caracteres
this.setupCharacterCounter();
// Vista previa en tiempo real
this.setupLivePreview();
},
/**
* Configurar contador de caracteres para textarea
*/
setupCharacterCounter() {
const messageTextarea = document.getElementById('topBarMessageText');
if (!messageTextarea) return;
messageTextarea.addEventListener('input', () => {
const count = messageTextarea.value.length;
const maxLength = 250;
const percentage = (count / maxLength) * 100;
const counter = document.getElementById('topBarMessageTextCount');
const progress = document.getElementById('topBarMessageTextProgress');
if (counter) {
counter.textContent = count;
// Cambiar color según proximidad al límite
counter.classList.remove('text-danger', 'text-warning', 'text-muted');
if (count > 230) {
counter.classList.add('text-danger');
} else if (count > 200) {
counter.classList.add('text-warning');
} else {
counter.classList.add('text-muted');
}
}
// Actualizar progress bar
if (progress) {
progress.style.width = percentage + '%';
progress.setAttribute('aria-valuenow', count);
// Cambiar color del progress bar
progress.classList.remove('bg-orange-primary', 'bg-warning', 'bg-danger');
if (count > 230) {
progress.classList.add('bg-danger');
} else if (count > 200) {
progress.classList.add('bg-warning');
} else {
progress.classList.add('bg-orange-primary');
}
}
});
// Trigger inicial para mostrar count actual
messageTextarea.dispatchEvent(new Event('input'));
},
/**
* Configurar vista previa en tiempo real
*/
setupLivePreview() {
const preview = document.getElementById('topBarPreview');
if (!preview) return;
// Campos que afectan la vista previa
const fields = {
iconClass: document.getElementById('topBarIconClass'),
showIcon: document.getElementById('topBarShowIcon'),
highlightText: document.getElementById('topBarHighlightText'),
messageText: document.getElementById('topBarMessageText'),
linkText: document.getElementById('topBarLinkText'),
showLink: document.getElementById('topBarShowLink'),
bgColor: document.getElementById('topBarBgColor'),
textColor: document.getElementById('topBarTextColor'),
highlightColor: document.getElementById('topBarHighlightColor'),
fontSize: document.getElementById('topBarFontSize')
};
// Función para actualizar la vista previa
const updatePreview = () => {
// Obtener valores
const iconClass = fields.iconClass.value || 'bi bi-megaphone-fill';
const showIcon = fields.showIcon.checked;
const highlightText = fields.highlightText.value;
const messageText = fields.messageText.value || 'Tu mensaje aquí...';
const linkText = fields.linkText.value || 'Ver más';
const showLink = fields.showLink.checked;
const bgColor = fields.bgColor.value || '#0E2337';
const textColor = fields.textColor.value || '#ffffff';
const highlightColor = fields.highlightColor.value || '#FF8600';
// Mapeo de tamaños de fuente
const fontSizeMap = {
'small': '0.8rem',
'normal': '0.9rem',
'large': '1rem'
};
const fontSize = fontSizeMap[fields.fontSize.value] || '0.9rem';
// Construir HTML de la vista previa
let html = '';
// Icono
if (showIcon && iconClass) {
html += `<i class="${iconClass}" style="font-size: 1.2rem; color: ${highlightColor};"></i>`;
}
// Texto destacado
if (highlightText) {
html += `<span style="font-weight: 700; color: ${highlightColor};">${highlightText}</span>`;
}
// Mensaje principal
html += `<span style="flex: 1; min-width: 300px; text-align: center;">${messageText}</span>`;
// Enlace
if (showLink && linkText) {
html += `<a href="#" style="color: ${textColor}; text-decoration: underline; white-space: nowrap; transition: color 0.3s;">${linkText}</a>`;
}
// Actualizar la vista previa
preview.innerHTML = html;
preview.style.backgroundColor = bgColor;
preview.style.color = textColor;
preview.style.fontSize = fontSize;
};
// Agregar listeners a todos los campos
Object.values(fields).forEach(field => {
if (field) {
field.addEventListener('input', updatePreview);
field.addEventListener('change', updatePreview);
}
});
// Actualización inicial
updatePreview();
},
/**
@@ -282,7 +147,8 @@ const AdminPanel = {
if (response.data.success) {
this.STATE.hasChanges = false;
document.getElementById('saveSettings').disabled = true;
const btn = document.getElementById('saveSettings');
if (btn) btn.disabled = true;
this.showNotice('Configuración guardada correctamente', 'success');
} else {
this.showNotice(response.data.data.message || 'Error al guardar', 'error');
@@ -297,34 +163,12 @@ const AdminPanel = {
/**
* Recolectar datos del formulario
* Cada componente agregará su sección aquí
* Cada componente agregará su sección aquí cuando se implemente
*/
collectFormData() {
return {
components: {
top_bar: {
enabled: document.getElementById('topBarEnabled').checked,
show_on_mobile: document.getElementById('topBarShowOnMobile').checked,
show_on_desktop: document.getElementById('topBarShowOnDesktop').checked,
icon_class: document.getElementById('topBarIconClass').value.trim(),
show_icon: document.getElementById('topBarShowIcon').checked,
highlight_text: document.getElementById('topBarHighlightText').value.trim(),
message_text: document.getElementById('topBarMessageText').value.trim(),
link_text: document.getElementById('topBarLinkText').value.trim(),
link_url: document.getElementById('topBarLinkUrl').value.trim(),
link_target: document.getElementById('topBarLinkTarget').value,
show_link: document.getElementById('topBarShowLink').checked,
custom_styles: {
background_color: this.getColorValue('topBarBgColor', ''),
text_color: this.getColorValue('topBarTextColor', ''),
highlight_color: this.getColorValue('topBarHighlightColor', ''),
link_hover_color: this.getColorValue('topBarLinkHoverColor', ''),
font_size: document.getElementById('topBarFontSize').value
}
}
// Navbar - Pendiente
// Hero - Pendiente
// Footer - Pendiente
// Los componentes se agregarán aquí cuando se ejecute el algoritmo
}
};
},
@@ -335,62 +179,7 @@ const AdminPanel = {
renderAllComponents() {
const components = this.STATE.settings.components || {};
// Top Bar
if (components.top_bar) {
this.renderTopBar(components.top_bar);
}
// Navbar - Pendiente
// Hero - Pendiente
// Footer - Pendiente
},
/**
* Renderizar Top Bar
*/
renderTopBar(topBar) {
document.getElementById('topBarEnabled').checked = topBar.enabled !== undefined ? topBar.enabled : true;
document.getElementById('topBarShowOnMobile').checked = topBar.show_on_mobile !== undefined ? topBar.show_on_mobile : true;
document.getElementById('topBarShowOnDesktop').checked = topBar.show_on_desktop !== undefined ? topBar.show_on_desktop : true;
document.getElementById('topBarIconClass').value = topBar.icon_class || 'bi bi-megaphone-fill';
document.getElementById('topBarShowIcon').checked = topBar.show_icon !== undefined ? topBar.show_icon : true;
document.getElementById('topBarHighlightText').value = topBar.highlight_text || 'Nuevo:';
document.getElementById('topBarMessageText').value = topBar.message_text || 'Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.';
document.getElementById('topBarLinkText').value = topBar.link_text || 'Ver Catálogo';
document.getElementById('topBarLinkUrl').value = topBar.link_url || '/catalogo';
document.getElementById('topBarLinkTarget').value = topBar.link_target || '_self';
document.getElementById('topBarShowLink').checked = topBar.show_link !== undefined ? topBar.show_link : true;
// Estilos personalizados
if (topBar.custom_styles) {
if (topBar.custom_styles.background_color) {
document.getElementById('topBarBgColor').value = topBar.custom_styles.background_color;
}
if (topBar.custom_styles.text_color) {
document.getElementById('topBarTextColor').value = topBar.custom_styles.text_color;
}
if (topBar.custom_styles.highlight_color) {
document.getElementById('topBarHighlightColor').value = topBar.custom_styles.highlight_color;
}
if (topBar.custom_styles.link_hover_color) {
document.getElementById('topBarLinkHoverColor').value = topBar.custom_styles.link_hover_color;
}
document.getElementById('topBarFontSize').value = topBar.custom_styles.font_size || 'normal';
}
// Trigger contador de caracteres
const messageTextarea = document.getElementById('topBarMessageText');
if (messageTextarea) {
messageTextarea.dispatchEvent(new Event('input'));
}
},
/**
* Utilidad: Obtener valor de color con fallback
*/
getColorValue(inputId, defaultValue) {
const input = document.getElementById(inputId);
const value = input ? input.value.trim() : '';
return value || defaultValue;
// Los métodos render de componentes se llamarán aquí cuando se implementen
},
/**

View File

@@ -1,191 +0,0 @@
/**
* Navbar Component - JavaScript Controller
*
* @package Apus_Theme
* @since 2.0.0
*/
window.NavbarComponent = {
/**
* Inicialización del componente
*/
init: function() {
console.log('Navbar component initialized');
// Actualizar valores hexadecimales de color pickers en tiempo real
this.initColorPickers();
},
/**
* Inicializar event listeners para color pickers
*/
initColorPickers: function() {
const colorPickers = [
{ input: 'navbarBgColor', display: 'navbarBgColorValue' },
{ input: 'navbarTextColor', display: 'navbarTextColorValue' },
{ input: 'navbarLinkHoverColor', display: 'navbarLinkHoverColorValue' },
{ input: 'navbarLinkHoverBgColor', display: 'navbarLinkHoverBgColorValue' },
{ input: 'navbarDropdownBgColor', display: 'navbarDropdownBgColorValue' },
{ input: 'navbarDropdownItemColor', display: 'navbarDropdownItemColorValue' },
{ input: 'navbarDropdownItemHoverColor', display: 'navbarDropdownItemHoverColorValue' }
];
colorPickers.forEach(function(picker) {
const inputEl = document.getElementById(picker.input);
const displayEl = document.getElementById(picker.display);
if (inputEl && displayEl) {
// Actualizar cuando cambia el color
inputEl.addEventListener('input', function() {
displayEl.textContent = inputEl.value.toUpperCase();
});
// Inicializar valor al cargar
displayEl.textContent = inputEl.value.toUpperCase();
}
});
},
/**
* Recolectar datos del formulario
* @returns {Object} Configuración del navbar
*/
collect: function() {
return {
// Grupo 1: Activación y Visibilidad
enabled: document.getElementById('navbarEnabled').checked,
show_on_mobile: document.getElementById('navbarShowOnMobile').checked,
show_on_desktop: document.getElementById('navbarShowOnDesktop').checked,
position: document.getElementById('navbarPosition').value,
responsive_breakpoint: document.getElementById('navbarBreakpoint').value,
// Grupo 4: Efectos (booleans)
enable_box_shadow: document.getElementById('navbarEnableBoxShadow').checked,
enable_underline_effect: document.getElementById('navbarEnableUnderlineEffect').checked,
enable_hover_background: document.getElementById('navbarEnableHoverBackground').checked,
// Grupo 6: Let's Talk Button
lets_talk_button: {
enabled: document.getElementById('navbarLetsTalkEnabled').checked,
text: document.getElementById('navbarLetsTalkText').value.trim(),
icon_class: document.getElementById('navbarLetsTalkIconClass').value.trim(),
show_icon: document.getElementById('navbarLetsTalkShowIcon').checked,
position: document.getElementById('navbarLetsTalkPosition').value
},
// Grupo 7: Dropdown
dropdown: {
enable_hover_desktop: document.getElementById('navbarDropdownEnableHoverDesktop').checked,
max_height: parseInt(document.getElementById('navbarDropdownMaxHeight').value) || 70,
border_radius: parseInt(document.getElementById('navbarDropdownBorderRadius').value) || 8,
item_padding_vertical: parseFloat(document.getElementById('navbarDropdownItemPaddingVertical').value) || 0.5,
item_padding_horizontal: parseFloat(document.getElementById('navbarDropdownItemPaddingHorizontal').value) || 1.25
},
// Grupos 2, 3, 5: Custom Styles
custom_styles: {
// Grupo 2: Colores
background_color: document.getElementById('navbarBgColor').value || '#1e3a5f',
text_color: document.getElementById('navbarTextColor').value || '#ffffff',
link_hover_color: document.getElementById('navbarLinkHoverColor').value || '#FF8600',
link_hover_bg_color: document.getElementById('navbarLinkHoverBgColor').value || '#FF8600',
dropdown_bg_color: document.getElementById('navbarDropdownBgColor').value || '#ffffff',
dropdown_item_color: document.getElementById('navbarDropdownItemColor').value || '#4A5568',
dropdown_item_hover_color: document.getElementById('navbarDropdownItemHoverColor').value || '#FF8600',
// Grupo 3: Tipografía
font_size: document.getElementById('navbarFontSize').value,
font_weight: document.getElementById('navbarFontWeight').value,
// Grupo 4: Efectos
box_shadow_intensity: document.getElementById('navbarBoxShadowIntensity').value,
border_radius: parseInt(document.getElementById('navbarBorderRadius').value) || 4,
// Grupo 5: Spacing
padding_vertical: parseFloat(document.getElementById('navbarPaddingVertical').value) || 0.75,
link_padding_vertical: parseFloat(document.getElementById('navbarLinkPaddingVertical').value) || 0.5,
link_padding_horizontal: parseFloat(document.getElementById('navbarLinkPaddingHorizontal').value) || 0.65,
// Grupo 8: Avanzado
z_index: parseInt(document.getElementById('navbarZIndex').value) || 1030,
transition_speed: document.getElementById('navbarTransitionSpeed').value || 'normal'
}
};
},
/**
* Renderizar configuración en el formulario
* @param {Object} config - Configuración del navbar
*/
render: function(config) {
if (!config) {
console.warn('No navbar config provided');
return;
}
// Grupo 1: Activación y Visibilidad
document.getElementById('navbarEnabled').checked = config.enabled !== undefined ? config.enabled : true;
document.getElementById('navbarShowOnMobile').checked = config.show_on_mobile !== undefined ? config.show_on_mobile : true;
document.getElementById('navbarShowOnDesktop').checked = config.show_on_desktop !== undefined ? config.show_on_desktop : true;
document.getElementById('navbarPosition').value = config.position || 'sticky';
document.getElementById('navbarBreakpoint').value = config.responsive_breakpoint || 'lg';
// Grupo 2: Colores Personalizados
if (config.custom_styles) {
document.getElementById('navbarBgColor').value = config.custom_styles.background_color || '#1e3a5f';
document.getElementById('navbarTextColor').value = config.custom_styles.text_color || '#ffffff';
document.getElementById('navbarLinkHoverColor').value = config.custom_styles.link_hover_color || '#FF8600';
document.getElementById('navbarLinkHoverBgColor').value = config.custom_styles.link_hover_bg_color || '#FF8600';
document.getElementById('navbarDropdownBgColor').value = config.custom_styles.dropdown_bg_color || '#ffffff';
document.getElementById('navbarDropdownItemColor').value = config.custom_styles.dropdown_item_color || '#4A5568';
document.getElementById('navbarDropdownItemHoverColor').value = config.custom_styles.dropdown_item_hover_color || '#FF8600';
}
// Grupo 3: Tipografía
if (config.custom_styles) {
document.getElementById('navbarFontSize').value = config.custom_styles.font_size || 'normal';
document.getElementById('navbarFontWeight').value = config.custom_styles.font_weight || '500';
}
// Grupo 4: Efectos Visuales
document.getElementById('navbarEnableBoxShadow').checked = config.enable_box_shadow !== undefined ? config.enable_box_shadow : true;
document.getElementById('navbarEnableUnderlineEffect').checked = config.enable_underline_effect !== undefined ? config.enable_underline_effect : true;
document.getElementById('navbarEnableHoverBackground').checked = config.enable_hover_background !== undefined ? config.enable_hover_background : true;
if (config.custom_styles) {
document.getElementById('navbarBoxShadowIntensity').value = config.custom_styles.box_shadow_intensity || 'normal';
document.getElementById('navbarBorderRadius').value = config.custom_styles.border_radius !== undefined ? config.custom_styles.border_radius : 4;
}
// Grupo 5: Spacing
if (config.custom_styles) {
document.getElementById('navbarPaddingVertical').value = config.custom_styles.padding_vertical !== undefined ? config.custom_styles.padding_vertical : 0.75;
document.getElementById('navbarLinkPaddingVertical').value = config.custom_styles.link_padding_vertical !== undefined ? config.custom_styles.link_padding_vertical : 0.5;
document.getElementById('navbarLinkPaddingHorizontal').value = config.custom_styles.link_padding_horizontal !== undefined ? config.custom_styles.link_padding_horizontal : 0.65;
}
// Grupo 8: Avanzado
if (config.custom_styles) {
document.getElementById('navbarZIndex').value = config.custom_styles.z_index !== undefined ? config.custom_styles.z_index : 1030;
document.getElementById('navbarTransitionSpeed').value = config.custom_styles.transition_speed || 'normal';
}
// Grupo 6: Let's Talk Button
if (config.lets_talk_button) {
document.getElementById('navbarLetsTalkEnabled').checked = config.lets_talk_button.enabled !== undefined ? config.lets_talk_button.enabled : true;
document.getElementById('navbarLetsTalkText').value = config.lets_talk_button.text || "Let's Talk";
document.getElementById('navbarLetsTalkIconClass').value = config.lets_talk_button.icon_class || 'bi bi-lightning-charge-fill';
document.getElementById('navbarLetsTalkShowIcon').checked = config.lets_talk_button.show_icon !== undefined ? config.lets_talk_button.show_icon : true;
document.getElementById('navbarLetsTalkPosition').value = config.lets_talk_button.position || 'right';
}
// Grupo 7: Dropdown
if (config.dropdown) {
document.getElementById('navbarDropdownEnableHoverDesktop').checked = config.dropdown.enable_hover_desktop !== undefined ? config.dropdown.enable_hover_desktop : true;
document.getElementById('navbarDropdownMaxHeight').value = config.dropdown.max_height !== undefined ? config.dropdown.max_height : 70;
document.getElementById('navbarDropdownBorderRadius').value = config.dropdown.border_radius !== undefined ? config.dropdown.border_radius : 8;
document.getElementById('navbarDropdownItemPaddingVertical').value = config.dropdown.item_padding_vertical !== undefined ? config.dropdown.item_padding_vertical : 0.5;
document.getElementById('navbarDropdownItemPaddingHorizontal').value = config.dropdown.item_padding_horizontal !== undefined ? config.dropdown.item_padding_horizontal : 1.25;
}
}
};

View File

@@ -1,604 +0,0 @@
<?php
/**
* Admin Panel - Hero Section Component
*
* Tab panel para configurar el Hero Section del tema
*
* @package Apus_Theme
* @since 2.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
?>
<!-- ============================================================
TAB: HERO SECTION CONFIGURATION
============================================================ -->
<div class="tab-pane fade" id="heroSectionTab" role="tabpanel" aria-labelledby="heroSection-tab">
<!-- ========================================
PATRÓN 1: HEADER CON GRADIENTE
======================================== -->
<div class="rounded p-4 mb-4 shadow text-white" style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%); border-left: 4px solid #FF8600;">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div>
<h3 class="h4 mb-1 fw-bold">
<i class="bi bi-image me-2" style="color: #FF8600;"></i>
Configuración del Hero Section
</h3>
<p class="mb-0 small" style="opacity: 0.85;">
Personaliza el banner principal con título y categorías
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-light" id="resetHeroSectionDefaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- ========================================
PATRÓN 2: LAYOUT 2 COLUMNAS
======================================== -->
<div class="row g-3">
<!-- ========================================
COLUMNA IZQUIERDA
======================================== -->
<div class="col-lg-6">
<!-- ========================================
GRUPO 1: ACTIVACIÓN Y VISIBILIDAD (OBLIGATORIO)
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-toggle-on me-2" style="color: #FF8600;"></i>
Activación y Visibilidad
</h5>
<!-- Switch 1: Enabled (OBLIGATORIO) -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionEnabled" checked>
<label class="form-check-label small" for="heroSectionEnabled" style="color: #495057;">
<i class="bi bi-power me-1" style="color: #FF8600;"></i>
<strong>Activar Hero Section</strong>
</label>
</div>
</div>
<!-- Switch 2: Show on Mobile (OBLIGATORIO) -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionShowOnMobile" checked>
<label class="form-check-label small" for="heroSectionShowOnMobile" style="color: #495057;">
<i class="bi bi-phone me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Mobile</strong> <span class="text-muted">(&lt;768px)</span>
</label>
</div>
</div>
<!-- Switch 3: Show on Desktop (OBLIGATORIO) -->
<div class="mb-0">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionShowOnDesktop" checked>
<label class="form-check-label small" for="heroSectionShowOnDesktop" style="color: #495057;">
<i class="bi bi-display me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Desktop</strong> <span class="text-muted">(≥768px)</span>
</label>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 2: CONTENIDO Y ESTRUCTURA
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-card-text me-2" style="color: #FF8600;"></i>
Contenido y Estructura
</h5>
<!-- Switch: Show Category Badges -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionShowCategoryBadges" checked>
<label class="form-check-label small" for="heroSectionShowCategoryBadges" style="color: #495057;">
<i class="bi bi-folder me-1" style="color: #FF8600;"></i>
<strong>Mostrar Category Badges</strong>
</label>
</div>
</div>
<!-- Text input: Badge Icon -->
<div class="mb-2">
<label for="heroSectionCategoryBadgeIcon" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-stars me-1" style="color: #FF8600;"></i>
Icono de Category Badge
</label>
<input type="text" id="heroSectionCategoryBadgeIcon" class="form-control form-control-sm" value="bi bi-folder-fill" placeholder="bi bi-...">
<small class="text-muted">Clase de Bootstrap Icons</small>
</div>
<!-- Textarea: Excluded Categories -->
<div class="mb-2">
<label for="heroSectionExcludedCategories" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-x-circle me-1" style="color: #FF8600;"></i>
Categorías Excluidas
</label>
<textarea id="heroSectionExcludedCategories" class="form-control form-control-sm" rows="2" placeholder="Una por línea">Uncategorized
Sin categoría</textarea>
<small class="text-muted">Una categoría por línea</small>
</div>
<!-- Compacted row: Alignment + Display Class -->
<div class="row g-2 mb-0">
<div class="col-6">
<label for="heroSectionTitleAlignment" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-text-center me-1" style="color: #FF8600;"></i>
Alineación Título
</label>
<select id="heroSectionTitleAlignment" class="form-select form-select-sm">
<option value="left">Izquierda</option>
<option value="center" selected>Centro</option>
<option value="right">Derecha</option>
</select>
</div>
<div class="col-6">
<label for="heroSectionTitleDisplayClass" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-type-h1 me-1" style="color: #FF8600;"></i>
Clase Display
</label>
<select id="heroSectionTitleDisplayClass" class="form-select form-select-sm">
<option value="display-1">display-1</option>
<option value="display-2">display-2</option>
<option value="display-3">display-3</option>
<option value="display-4">display-4</option>
<option value="display-5" selected>display-5</option>
<option value="display-6">display-6</option>
</select>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 3: COLORES DEL HERO
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-palette me-2" style="color: #FF8600;"></i>
Colores del Hero
</h5>
<!-- Switch: Use Gradient Background -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionUseGradientBackground" checked>
<label class="form-check-label small" for="heroSectionUseGradientBackground" style="color: #495057;">
<i class="bi bi-palette-fill me-1" style="color: #FF8600;"></i>
<strong>Usar Gradiente de Fondo</strong>
</label>
</div>
</div>
<!-- Color pickers: Grid 2x2 (primera fila) -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionGradientStartColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-paint-bucket me-1" style="color: #FF8600;"></i>
Color Gradiente Inicio
</label>
<input type="color" id="heroSectionGradientStartColor" class="form-control form-control-color w-100" value="#1e3a5f" title="Seleccionar color gradiente inicio">
<small class="text-muted d-block mt-1" id="heroSectionGradientStartColorValue">#1E3A5F</small>
</div>
<div class="col-6">
<label for="heroSectionGradientEndColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-paint-bucket-fill me-1" style="color: #FF8600;"></i>
Color Gradiente Fin
</label>
<input type="color" id="heroSectionGradientEndColor" class="form-control form-control-color w-100" value="#2c5282" title="Seleccionar color gradiente fin">
<small class="text-muted d-block mt-1" id="heroSectionGradientEndColorValue">#2C5282</small>
</div>
</div>
<!-- Color pickers: Grid 2x2 (segunda fila) -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionHeroTextColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-fonts me-1" style="color: #FF8600;"></i>
Color Texto H1
</label>
<input type="color" id="heroSectionHeroTextColor" class="form-control form-control-color w-100" value="#ffffff" title="Seleccionar color texto">
<small class="text-muted d-block mt-1" id="heroSectionHeroTextColorValue">#ffffff</small>
</div>
<div class="col-6">
<label for="heroSectionSolidBackgroundColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-square-fill me-1" style="color: #FF8600;"></i>
Color Fondo Sólido
</label>
<input type="color" id="heroSectionSolidBackgroundColor" class="form-control form-control-color w-100" value="#1e3a5f" title="Seleccionar color fondo sólido">
<small class="text-muted d-block mt-1" id="heroSectionSolidBackgroundColorValue">#1E3A5F</small>
</div>
</div>
<!-- Range: Gradient Angle -->
<div class="mb-0">
<label for="heroSectionGradientAngle" class="form-label small mb-1 fw-semibold d-flex justify-content-between align-items-center" style="color: #495057;">
<span>
<i class="bi bi-arrow-clockwise me-1" style="color: #FF8600;"></i>
Ángulo del Gradiente
</span>
<span class="badge bg-secondary" id="heroSectionGradientAngleValue">135°</span>
</label>
<input type="range" id="heroSectionGradientAngle" class="form-range" min="0" max="360" step="1" value="135">
</div>
</div>
</div>
<!-- ========================================
GRUPO 4: COLORES DE CATEGORY BADGES
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-folder-fill me-2" style="color: #FF8600;"></i>
Colores de Category Badges
</h5>
<!-- Color pickers: Grid 2x2 (primera fila) -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionBadgeBgColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-paint-bucket me-1" style="color: #FF8600;"></i>
Background Badge
</label>
<input type="text" id="heroSectionBadgeBgColor" class="form-control form-control-sm" value="rgba(255, 255, 255, 0.15)" placeholder="rgba(...)">
<small class="text-muted">Soporta RGBA</small>
</div>
<div class="col-6">
<label for="heroSectionBadgeBgHoverColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-hand-index me-1" style="color: #FF8600;"></i>
Background Hover
</label>
<input type="text" id="heroSectionBadgeBgHoverColor" class="form-control form-control-sm" value="rgba(255, 133, 0, 0.2)" placeholder="rgba(...)">
<small class="text-muted">Soporta RGBA</small>
</div>
</div>
<!-- Color pickers: Grid 2x2 (segunda fila) -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionBadgeBorderColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-border me-1" style="color: #FF8600;"></i>
Border Badge
</label>
<input type="text" id="heroSectionBadgeBorderColor" class="form-control form-control-sm" value="rgba(255, 255, 255, 0.2)" placeholder="rgba(...)">
<small class="text-muted">Soporta RGBA</small>
</div>
<div class="col-6">
<label for="heroSectionBadgeTextColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-fonts me-1" style="color: #FF8600;"></i>
Texto Badge
</label>
<input type="text" id="heroSectionBadgeTextColor" class="form-control form-control-sm" value="rgba(255, 255, 255, 0.95)" placeholder="rgba(...)">
<small class="text-muted">Soporta RGBA</small>
</div>
</div>
<!-- Color picker: Icon Color (full width) -->
<div class="mb-0">
<label for="heroSectionBadgeIconColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-stars me-1" style="color: #FF8600;"></i>
Color Icono Badge
</label>
<input type="color" id="heroSectionBadgeIconColor" class="form-control form-control-color w-100" value="#FFB800" title="Seleccionar color icono">
<small class="text-muted d-block mt-1" id="heroSectionBadgeIconColorValue">#FFB800</small>
</div>
</div>
</div>
</div>
<!-- ========================================
COLUMNA DERECHA
======================================== -->
<div class="col-lg-6">
<!-- ========================================
GRUPO 5: ESPACIADO Y DIMENSIONES
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-arrows-fullscreen me-2" style="color: #FF8600;"></i>
Espaciado y Dimensiones
</h5>
<!-- Hero padding compactado -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionHeroPaddingVertical" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrows-vertical me-1" style="color: #FF8600;"></i>
Padding Vertical (rem)
</label>
<input type="number" id="heroSectionHeroPaddingVertical" class="form-control form-control-sm" value="3" min="0" max="10" step="0.5">
</div>
<div class="col-6">
<label for="heroSectionHeroPaddingHorizontal" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrows-expand me-1" style="color: #FF8600;"></i>
Padding Horizontal (rem)
</label>
<input type="number" id="heroSectionHeroPaddingHorizontal" class="form-control form-control-sm" value="0" min="0" max="10" step="0.5">
</div>
</div>
<!-- Margin + Gap compactado -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionHeroMarginBottom" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrow-down me-1" style="color: #FF8600;"></i>
Margin Bottom (rem)
</label>
<input type="number" id="heroSectionHeroMarginBottom" class="form-control form-control-sm" value="1.5" min="0" max="5" step="0.5">
</div>
<div class="col-6">
<label for="heroSectionBadgesGap" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-distribute-horizontal me-1" style="color: #FF8600;"></i>
Gap Badges (rem)
</label>
<input type="number" id="heroSectionBadgesGap" class="form-control form-control-sm" value="0.5" min="0" max="3" step="0.1">
</div>
</div>
<!-- Badge padding compactado -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionBadgePaddingVertical" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrows-vertical me-1" style="color: #FF8600;"></i>
Badge Padding V (rem)
</label>
<input type="number" id="heroSectionBadgePaddingVertical" class="form-control form-control-sm" value="0.375" min="0" max="2" step="0.125">
</div>
<div class="col-6">
<label for="heroSectionBadgePaddingHorizontal" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrows-expand me-1" style="color: #FF8600;"></i>
Badge Padding H (rem)
</label>
<input type="number" id="heroSectionBadgePaddingHorizontal" class="form-control form-control-sm" value="0.875" min="0" max="2" step="0.125">
</div>
</div>
<!-- Border radius -->
<div class="mb-0">
<label for="heroSectionBadgeBorderRadius" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-diamond me-1" style="color: #FF8600;"></i>
Border Radius Badge (px)
</label>
<input type="number" id="heroSectionBadgeBorderRadius" class="form-control form-control-sm" value="20" min="0" max="50" step="1">
</div>
</div>
</div>
<!-- ========================================
GRUPO 6: TIPOGRAFÍA
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-type me-2" style="color: #FF8600;"></i>
Tipografía
</h5>
<!-- H1 Font Weight + Badge Font Size compactado -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="heroSectionH1FontWeight" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-type-bold me-1" style="color: #FF8600;"></i>
Font Weight H1
</label>
<select id="heroSectionH1FontWeight" class="form-select form-select-sm">
<option value="400">400 (Normal)</option>
<option value="500">500 (Medium)</option>
<option value="600">600 (Semibold)</option>
<option value="700" selected>700 (Bold)</option>
</select>
</div>
<div class="col-6">
<label for="heroSectionBadgeFontSize" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-fonts me-1" style="color: #FF8600;"></i>
Badge Font Size (rem)
</label>
<input type="number" id="heroSectionBadgeFontSize" class="form-control form-control-sm" value="0.813" min="0.5" max="2" step="0.125">
</div>
</div>
<!-- Badge Font Weight + H1 Line Height compactado -->
<div class="row g-2 mb-0">
<div class="col-6">
<label for="heroSectionBadgeFontWeight" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-type-bold me-1" style="color: #FF8600;"></i>
Font Weight Badge
</label>
<select id="heroSectionBadgeFontWeight" class="form-select form-select-sm">
<option value="400">400 (Normal)</option>
<option value="500" selected>500 (Medium)</option>
<option value="600">600 (Semibold)</option>
<option value="700">700 (Bold)</option>
</select>
</div>
<div class="col-6">
<label for="heroSectionH1LineHeight" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-text-paragraph me-1" style="color: #FF8600;"></i>
Line Height H1
</label>
<input type="number" id="heroSectionH1LineHeight" class="form-control form-control-sm" value="1.4" min="1" max="3" step="0.1">
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 7: EFECTOS VISUALES
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-stars me-2" style="color: #FF8600;"></i>
Efectos Visuales
</h5>
<!-- Switch: Enable H1 Text Shadow -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionEnableH1TextShadow" checked>
<label class="form-check-label small" for="heroSectionEnableH1TextShadow" style="color: #495057;">
<i class="bi bi-sun me-1" style="color: #FF8600;"></i>
<strong>Habilitar Text Shadow H1</strong>
</label>
</div>
</div>
<!-- Text input: H1 Text Shadow -->
<div class="mb-2">
<label for="heroSectionH1TextShadow" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-droplet me-1" style="color: #FF8600;"></i>
Text Shadow H1
</label>
<input type="text" id="heroSectionH1TextShadow" class="form-control form-control-sm" value="1px 1px 2px rgba(0, 0, 0, 0.2)" placeholder="CSS shadow">
<small class="text-muted">Sintaxis CSS: x y blur color</small>
</div>
<!-- Switch: Enable Hero Box Shadow -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionEnableHeroBoxShadow" checked>
<label class="form-check-label small" for="heroSectionEnableHeroBoxShadow" style="color: #495057;">
<i class="bi bi-box me-1" style="color: #FF8600;"></i>
<strong>Habilitar Box Shadow Hero</strong>
</label>
</div>
</div>
<!-- Text input: Hero Box Shadow -->
<div class="mb-2">
<label for="heroSectionHeroBoxShadow" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-box-seam me-1" style="color: #FF8600;"></i>
Box Shadow Hero
</label>
<input type="text" id="heroSectionHeroBoxShadow" class="form-control form-control-sm" value="0 4px 16px rgba(30, 58, 95, 0.25)" placeholder="CSS shadow">
<small class="text-muted">Sintaxis CSS: x y blur spread color</small>
</div>
<!-- Switch: Enable Badge Backdrop Filter -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="heroSectionEnableBadgeBackdropFilter" checked>
<label class="form-check-label small" for="heroSectionEnableBadgeBackdropFilter" style="color: #495057;">
<i class="bi bi-bounding-box me-1" style="color: #FF8600;"></i>
<strong>Habilitar Backdrop Filter Badge</strong>
</label>
</div>
</div>
<!-- Text input: Badge Backdrop Filter -->
<div class="mb-0">
<label for="heroSectionBadgeBackdropFilter" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-filter me-1" style="color: #FF8600;"></i>
Backdrop Filter Badge
</label>
<input type="text" id="heroSectionBadgeBackdropFilter" class="form-control form-control-sm" value="blur(10px)" placeholder="CSS filter">
<small class="text-muted">Ej: blur(10px), brightness(1.2)</small>
</div>
</div>
</div>
<!-- ========================================
GRUPO 8: TRANSICIONES Y ANIMACIONES
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-lightning me-2" style="color: #FF8600;"></i>
Transiciones y Animaciones
</h5>
<!-- Compacted row: Transition Speed + Hover Effect -->
<div class="row g-2 mb-0">
<div class="col-6">
<label for="heroSectionBadgeTransitionSpeed" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-speedometer me-1" style="color: #FF8600;"></i>
Velocidad Transición
</label>
<select id="heroSectionBadgeTransitionSpeed" class="form-select form-select-sm">
<option value="fast">Rápida (0.15s)</option>
<option value="normal" selected>Normal (0.3s)</option>
<option value="slow">Lenta (0.5s)</option>
</select>
</div>
<div class="col-6">
<label for="heroSectionBadgeHoverEffect" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-hand-index me-1" style="color: #FF8600;"></i>
Efecto Hover
</label>
<select id="heroSectionBadgeHoverEffect" class="form-select form-select-sm">
<option value="none">Ninguno</option>
<option value="background" selected>Background</option>
<option value="scale">Escala</option>
<option value="brightness">Brillo</option>
</select>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 9: AVANZADO
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-code-slash me-2" style="color: #FF8600;"></i>
Avanzado
</h5>
<!-- Text input: Custom Hero Classes -->
<div class="mb-2">
<label for="heroSectionCustomHeroClasses" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-braces me-1" style="color: #FF8600;"></i>
Custom CSS Classes Hero
</label>
<input type="text" id="heroSectionCustomHeroClasses" class="form-control form-control-sm" value="" placeholder="custom-class-1 custom-class-2">
<small class="text-muted">Clases CSS adicionales separadas por espacio</small>
</div>
<!-- Text input: Custom Badge Classes -->
<div class="mb-0">
<label for="heroSectionCustomBadgeClasses" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-braces-asterisk me-1" style="color: #FF8600;"></i>
Custom CSS Classes Badge
</label>
<input type="text" id="heroSectionCustomBadgeClasses" class="form-control form-control-sm" value="" placeholder="badge-custom-1">
<small class="text-muted">Clases CSS adicionales para badges</small>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,393 +0,0 @@
<?php
/**
* Component: Let's Talk Button Configuration
*
* @package Apus_Theme
* @since 2.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
?>
<!-- ============================================================
TAB: BOTÓN LET'S TALK CONFIGURATION
============================================================ -->
<div class="tab-pane fade" id="letsTalkButtonTab" role="tabpanel" aria-labelledby="lets-talk-button-config-tab">
<!-- ========================================
PATRÓN 1: HEADER CON GRADIENTE
======================================== -->
<div class="rounded p-4 mb-4 shadow text-white" style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%); border-left: 4px solid #FF8600;">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div>
<h3 class="h4 mb-1 fw-bold">
<i class="bi bi-lightning-charge-fill me-2" style="color: #FF8600;"></i>
Configuración del Botón Let's Talk
</h3>
<p class="mb-0 small" style="opacity: 0.85;">
Personaliza el botón de contacto "Let's Talk" del navbar
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-light" id="resetLetsTalkButtonDefaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- ========================================
PATRÓN 2: LAYOUT 2 COLUMNAS
======================================== -->
<div class="row g-3">
<div class="col-lg-6">
<!-- ========================================
GRUPO 1: ACTIVACIÓN Y VISIBILIDAD (3 campos)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
PATRÓN 4: 3 SWITCHES OBLIGATORIOS
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-toggle-on me-2" style="color: #FF8600;"></i>
Activación y Visibilidad
</h5>
<!-- Switch 1: Enabled (OBLIGATORIO) -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="letsTalkButtonEnabled" checked>
<label class="form-check-label small" for="letsTalkButtonEnabled" style="color: #495057;">
<i class="bi bi-power me-1" style="color: #FF8600;"></i>
<strong>Activar Botón Let's Talk</strong>
</label>
</div>
</div>
<!-- Switch 2: Show on Mobile (OBLIGATORIO) -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="letsTalkButtonShowOnMobile" checked>
<label class="form-check-label small" for="letsTalkButtonShowOnMobile" style="color: #495057;">
<i class="bi bi-phone me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Mobile</strong> <span class="text-muted">(&lt;768px)</span>
</label>
</div>
</div>
<!-- Switch 3: Show on Desktop (OBLIGATORIO) -->
<div class="mb-0">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="letsTalkButtonShowOnDesktop" checked>
<label class="form-check-label small" for="letsTalkButtonShowOnDesktop" style="color: #495057;">
<i class="bi bi-display me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Desktop</strong> <span class="text-muted">(≥768px)</span>
</label>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 2: CONTENIDO (3 campos)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-chat-text me-2" style="color: #FF8600;"></i>
Contenido
</h5>
<!-- Switch: show_icon -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="letsTalkButtonShowIcon" checked>
<label class="form-check-label small" for="letsTalkButtonShowIcon" style="color: #495057;">
<i class="bi bi-eye me-1" style="color: #FF8600;"></i>
<strong>Mostrar icono</strong>
</label>
</div>
</div>
<!-- Text inputs compactados: text + icon_class -->
<div class="row g-2 mb-0">
<div class="col-6">
<label for="letsTalkButtonText" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-fonts me-1" style="color: #FF8600;"></i>
Texto del botón
</label>
<input type="text" id="letsTalkButtonText" class="form-control form-control-sm" value="Let's Talk" maxlength="30">
<small class="text-muted">Máximo 30 caracteres</small>
</div>
<div class="col-6">
<label for="letsTalkButtonIconClass" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-star me-1" style="color: #FF8600;"></i>
Clase del icono
</label>
<input type="text" id="letsTalkButtonIconClass" class="form-control form-control-sm" value="bi bi-lightning-charge-fill" placeholder="bi bi-...">
<small class="text-muted">Bootstrap Icons</small>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 3: TIPOGRAFÍA (1 campo)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-fonts me-2" style="color: #FF8600;"></i>
Tipografía
</h5>
<!-- Select: font_weight -->
<div class="mb-0">
<label for="letsTalkButtonFontWeight" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-type-bold me-1" style="color: #FF8600;"></i>
Peso de fuente
</label>
<select id="letsTalkButtonFontWeight" class="form-select form-select-sm">
<option value="400">Normal (400)</option>
<option value="500">Medium (500)</option>
<option value="600" selected>Semibold (600)</option>
<option value="700">Bold (700)</option>
</select>
</div>
</div>
</div>
<!-- ========================================
GRUPO 4: COMPORTAMIENTO (1 campo)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-gear me-2" style="color: #FF8600;"></i>
Comportamiento
</h5>
<!-- Text input: modal_target -->
<div class="mb-0">
<label for="letsTalkButtonModalTarget" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-window me-1" style="color: #FF8600;"></i>
ID del modal
</label>
<input type="text" id="letsTalkButtonModalTarget" class="form-control form-control-sm" value="#contactModal" maxlength="50" placeholder="#nombreModal">
<small class="text-muted">Debe comenzar con #</small>
</div>
</div>
</div>
<!-- ========================================
GRUPO 5: ESPACIADO Y POSICIÓN (3 campos)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-arrows-angle-expand me-2" style="color: #FF8600;"></i>
Espaciado y Posición
</h5>
<!-- Number inputs compactados: padding_vertical + padding_horizontal -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="letsTalkButtonPaddingVertical" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrows-vertical me-1" style="color: #FF8600;"></i>
Padding vertical
</label>
<input type="number" id="letsTalkButtonPaddingVertical" class="form-control form-control-sm" value="0.5" min="0" max="3" step="0.1">
<small class="text-muted">En rem (0-3)</small>
</div>
<div class="col-6">
<label for="letsTalkButtonPaddingHorizontal" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-arrows-horizontal me-1" style="color: #FF8600;"></i>
Padding horizontal
</label>
<input type="number" id="letsTalkButtonPaddingHorizontal" class="form-control form-control-sm" value="1.5" min="0" max="5" step="0.1">
<small class="text-muted">En rem (0-5)</small>
</div>
</div>
<!-- Select: position -->
<div class="mb-0">
<label for="letsTalkButtonPosition" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-pin-angle me-1" style="color: #FF8600;"></i>
Posición en navbar
</label>
<select id="letsTalkButtonPosition" class="form-select form-select-sm">
<option value="left">Izquierda</option>
<option value="center">Centro</option>
<option value="right" selected>Derecha</option>
</select>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<!-- ========================================
GRUPO 6: COLORES PERSONALIZADOS (4 campos)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
PATRÓN 5: COLOR PICKERS EN GRID 2X2
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-palette me-2" style="color: #FF8600;"></i>
Colores Personalizados
</h5>
<!-- Color pickers en grid 2x2 -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="letsTalkButtonBgColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-paint-bucket me-1" style="color: #FF8600;"></i>
Color de fondo
</label>
<input type="color" id="letsTalkButtonBgColor" class="form-control form-control-color w-100" value="#FF8600" title="Seleccionar color de fondo">
<small class="text-muted d-block mt-1" id="letsTalkButtonBgColorValue">#FF8600</small>
</div>
<div class="col-6">
<label for="letsTalkButtonBgHoverColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-cursor me-1" style="color: #FF8600;"></i>
Color hover
</label>
<input type="color" id="letsTalkButtonBgHoverColor" class="form-control form-control-color w-100" value="#FF6B35" title="Seleccionar color hover">
<small class="text-muted d-block mt-1" id="letsTalkButtonBgHoverColorValue">#FF6B35</small>
</div>
</div>
<div class="row g-2 mb-0">
<div class="col-6">
<label for="letsTalkButtonTextColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-type me-1" style="color: #FF8600;"></i>
Color de texto
</label>
<input type="color" id="letsTalkButtonTextColor" class="form-control form-control-color w-100" value="#ffffff" title="Seleccionar color de texto">
<small class="text-muted d-block mt-1" id="letsTalkButtonTextColorValue">#ffffff</small>
</div>
<div class="col-6">
<label for="letsTalkButtonIconColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-star-fill me-1" style="color: #FF8600;"></i>
Color icono
</label>
<input type="color" id="letsTalkButtonIconColor" class="form-control form-control-color w-100" value="#ffffff" title="Seleccionar color icono">
<small class="text-muted d-block mt-1" id="letsTalkButtonIconColorValue">#ffffff</small>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 7: ESTILOS AVANZADOS (8 campos)
PATRÓN 3: CARD CON BORDER-LEFT NAVY
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-sliders me-2" style="color: #FF8600;"></i>
Estilos Avanzados
</h5>
<!-- Number inputs compactados: border_radius + border_width -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="letsTalkButtonBorderRadius" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-border-radius me-1" style="color: #FF8600;"></i>
Radio esquinas
</label>
<input type="number" id="letsTalkButtonBorderRadius" class="form-control form-control-sm" value="6" min="0" max="30" step="1">
<small class="text-muted">En px (0-30)</small>
</div>
<div class="col-6">
<label for="letsTalkButtonBorderWidth" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-border-width me-1" style="color: #FF8600;"></i>
Ancho de borde
</label>
<input type="number" id="letsTalkButtonBorderWidth" class="form-control form-control-sm" value="0" min="0" max="10" step="1">
<small class="text-muted">En px (0-10)</small>
</div>
</div>
<!-- Border color + border style compactados -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="letsTalkButtonBorderColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-border-style me-1" style="color: #FF8600;"></i>
Color borde
</label>
<input type="color" id="letsTalkButtonBorderColor" class="form-control form-control-color w-100" value="#000000" title="Seleccionar color borde">
<small class="text-muted d-block mt-1" id="letsTalkButtonBorderColorValue">#000000</small>
</div>
<div class="col-6">
<label for="letsTalkButtonBorderStyle" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-dash-lg me-1" style="color: #FF8600;"></i>
Estilo borde
</label>
<select id="letsTalkButtonBorderStyle" class="form-select form-select-sm">
<option value="solid" selected>Sólido</option>
<option value="dashed">Guiones</option>
<option value="dotted">Puntos</option>
</select>
</div>
</div>
<!-- Switch: enable_box_shadow -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="letsTalkButtonEnableBoxShadow">
<label class="form-check-label small" for="letsTalkButtonEnableBoxShadow" style="color: #495057;">
<i class="bi bi-box-seam me-1" style="color: #FF8600;"></i>
<strong>Habilitar sombra</strong>
</label>
</div>
</div>
<!-- Text input: box_shadow -->
<div class="mb-2">
<label for="letsTalkButtonBoxShadow" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-shadow me-1" style="color: #FF8600;"></i>
CSS box-shadow
</label>
<input type="text" id="letsTalkButtonBoxShadow" class="form-control form-control-sm" value="0 2px 8px rgba(0, 0, 0, 0.15)" maxlength="100">
<small class="text-muted">Ejemplo: 0 4px 12px rgba(255, 134, 0, 0.3)</small>
</div>
<!-- Selects compactados: transition_speed + hover_effect -->
<div class="row g-2 mb-0">
<div class="col-6">
<label for="letsTalkButtonTransitionSpeed" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-speedometer me-1" style="color: #FF8600;"></i>
Velocidad
</label>
<select id="letsTalkButtonTransitionSpeed" class="form-select form-select-sm">
<option value="fast">Rápido (0.2s)</option>
<option value="normal" selected>Normal (0.3s)</option>
<option value="slow">Lento (0.5s)</option>
</select>
</div>
<div class="col-6">
<label for="letsTalkButtonHoverEffect" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-magic me-1" style="color: #FF8600;"></i>
Efecto hover
</label>
<select id="letsTalkButtonHoverEffect" class="form-select form-select-sm">
<option value="none" selected>Ninguno</option>
<option value="scale">Escala (1.05)</option>
<option value="brightness">Brillo</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,585 +0,0 @@
<?php
/**
* Navbar Component - Admin Interface v2.0
* Sigue los 4 patrones obligatorios de Top Bar
*
* @package Apus_Theme
* @since 2.0.0
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
?>
<!-- ============================================================
TAB: NAVBAR CONFIGURATION
============================================================ -->
<div class="tab-pane fade"
id="navbarTab"
role="tabpanel"
aria-labelledby="navbar-config-tab">
<!-- ========================================
PATRÓN 1: HEADER CON GRADIENTE
======================================== -->
<div class="rounded p-4 mb-4 shadow text-white" style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%); border-left: 4px solid #FF8600;">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div>
<h3 class="h4 mb-1 fw-bold">
<i class="bi bi-list me-2" style="color: #FF8600;"></i>
Configuración Navbar
</h3>
<p class="mb-0 small" style="opacity: 0.85;">
Personaliza el menú de navegación principal de tu sitio
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-light" id="resetNavbarDefaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- ========================================
PATRÓN 2: LAYOUT 2 COLUMNAS
======================================== -->
<div class="row g-3">
<!-- ========================================
COLUMNA IZQUIERDA
======================================== -->
<div class="col-lg-6">
<!-- ========================================
GRUPO 1: ACTIVACIÓN Y VISIBILIDAD
PATRÓN 3: CARD CON BORDER-LEFT NAVY
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-toggle-on me-2" style="color: #FF8600;"></i>
Activación y Visibilidad
</h5>
<!-- PATRÓN 4: SWITCHES VERTICALES -->
<!-- Enabled -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarEnabled" checked="">
<label class="form-check-label small" for="navbarEnabled" style="color: #495057;">
<i class="bi bi-power me-1" style="color: #FF8600;"></i>
<strong>Activar Navbar</strong>
</label>
</div>
</div>
<!-- Show on Mobile -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarShowOnMobile" checked="">
<label class="form-check-label small" for="navbarShowOnMobile" style="color: #495057;">
<i class="bi bi-phone me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Mobile</strong> <span class="text-muted">(&lt;768px)</span>
</label>
</div>
</div>
<!-- Show on Desktop -->
<div class="mb-0">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarShowOnDesktop" checked="">
<label class="form-check-label small" for="navbarShowOnDesktop" style="color: #495057;">
<i class="bi bi-display me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Desktop</strong> <span class="text-muted">(≥768px)</span>
</label>
</div>
</div>
<!-- Selects compactados en fila -->
<div class="row g-2 mt-3">
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarPosition" class="text-secondary fw-medium mb-1">
Posición
</label>
<select id="navbarPosition" class="form-select form-select-sm">
<option value="sticky" selected>Sticky (fija al scroll)</option>
<option value="static">Static (normal)</option>
<option value="fixed">Fixed (siempre fija)</option>
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarBreakpoint" class="text-secondary fw-medium mb-1">
Breakpoint
</label>
<select id="navbarBreakpoint" class="form-select form-select-sm">
<option value="sm">SM (576px)</option>
<option value="md">MD (768px)</option>
<option value="lg" selected>LG (992px)</option>
<option value="xl">XL (1200px)</option>
<option value="xxl">XXL (1400px)</option>
</select>
</div>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 2: COLORES PERSONALIZADOS
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-palette me-2" style="color: #FF8600;"></i>
Colores Personalizados
</h5>
<!-- 7 colores en grid 2x2 (patrón Top Bar) -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="navbarBgColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-paint-bucket me-1" style="color: #FF8600;"></i>
Color de fondo
</label>
<input type="color" id="navbarBgColor" class="form-control form-control-color w-100" value="#1e3a5f" title="Seleccionar color de fondo">
<small class="text-muted d-block mt-1" id="navbarBgColorValue">#1e3a5f</small>
</div>
<div class="col-6">
<label for="navbarTextColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-fonts me-1" style="color: #FF8600;"></i>
Color de texto
</label>
<input type="color" id="navbarTextColor" class="form-control form-control-color w-100" value="#ffffff" title="Seleccionar color de texto">
<small class="text-muted d-block mt-1" id="navbarTextColorValue">#ffffff</small>
</div>
<div class="col-6">
<label for="navbarLinkHoverColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-cursor me-1" style="color: #FF8600;"></i>
Color hover links
</label>
<input type="color" id="navbarLinkHoverColor" class="form-control form-control-color w-100" value="#FF8600" title="Seleccionar color hover enlaces">
<small class="text-muted d-block mt-1" id="navbarLinkHoverColorValue">#FF8600</small>
</div>
<div class="col-6">
<label for="navbarLinkHoverBgColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-square-fill me-1" style="color: #FF8600;"></i>
Background hover
</label>
<input type="color" id="navbarLinkHoverBgColor" class="form-control form-control-color w-100" value="#FF8600" title="Seleccionar color fondo hover">
<small class="text-muted d-block mt-1" id="navbarLinkHoverBgColorValue">#FF8600</small>
</div>
<div class="col-6">
<label for="navbarDropdownBgColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-card-text me-1" style="color: #FF8600;"></i>
Dropdown BG
</label>
<input type="color" id="navbarDropdownBgColor" class="form-control form-control-color w-100" value="#ffffff" title="Seleccionar color fondo dropdown">
<small class="text-muted d-block mt-1" id="navbarDropdownBgColorValue">#ffffff</small>
</div>
<div class="col-6">
<label for="navbarDropdownItemColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-text-left me-1" style="color: #FF8600;"></i>
Item Color
</label>
<input type="color" id="navbarDropdownItemColor" class="form-control form-control-color w-100" value="#495057" title="Seleccionar color items dropdown">
<small class="text-muted d-block mt-1" id="navbarDropdownItemColorValue">#495057</small>
</div>
<div class="col-6">
<label for="navbarDropdownItemHoverColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-hand-index me-1" style="color: #FF8600;"></i>
Item Hover
</label>
<input type="color" id="navbarDropdownItemHoverColor" class="form-control form-control-color w-100" value="#FF8600" title="Seleccionar color hover items dropdown">
<small class="text-muted d-block mt-1" id="navbarDropdownItemHoverColorValue">#FF8600</small>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 3: TIPOGRAFÍA
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-fonts me-2" style="color: #FF8600;"></i>
Tipografía
</h5>
<div class="row g-2">
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarFontSize" class="text-secondary fw-medium mb-1">
Tamaño de fuente
</label>
<select id="navbarFontSize" class="form-select form-select-sm">
<option value="small">Pequeño (0.8rem)</option>
<option value="normal" selected>Normal (0.9rem)</option>
<option value="large">Grande (1rem)</option>
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarFontWeight" class="text-secondary fw-medium mb-1">
Peso de fuente
</label>
<select id="navbarFontWeight" class="form-select form-select-sm">
<option value="400">Normal (400)</option>
<option value="500" selected>Medium (500)</option>
<option value="600">Semibold (600)</option>
<option value="700">Bold (700)</option>
</select>
</div>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 4: EFECTOS VISUALES
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-magic me-2" style="color: #FF8600;"></i>
Efectos Visuales
</h5>
<!-- Switches verticales -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarEnableBoxShadow" checked="">
<label class="form-check-label small" for="navbarEnableBoxShadow" style="color: #495057;">
<i class="bi bi-box-arrow-down me-1" style="color: #FF8600;"></i>
<strong>Habilitar Box Shadow</strong>
</label>
</div>
</div>
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarEnableUnderlineEffect" checked="">
<label class="form-check-label small" for="navbarEnableUnderlineEffect" style="color: #495057;">
<i class="bi bi-dash-lg me-1" style="color: #FF8600;"></i>
<strong>Línea animada al hover</strong>
</label>
</div>
</div>
<div class="mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarEnableHoverBackground" checked="">
<label class="form-check-label small" for="navbarEnableHoverBackground" style="color: #495057;">
<i class="bi bi-square-fill me-1" style="color: #FF8600;"></i>
<strong>Background al hover</strong>
</label>
</div>
</div>
<!-- Selects y números compactados -->
<div class="row g-2">
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarBoxShadowIntensity" class="text-secondary fw-medium mb-1">
Intensidad sombra
</label>
<select id="navbarBoxShadowIntensity" class="form-select form-select-sm">
<option value="none">Sin sombra</option>
<option value="light">Ligera</option>
<option value="normal" selected>Normal</option>
<option value="strong">Fuerte</option>
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarBorderRadius" class="text-secondary fw-medium mb-1">
Border radius (px)
</label>
<input type="number"
id="navbarBorderRadius"
class="form-control form-control-sm"
value="4"
min="0"
max="20">
</div>
</div>
</div>
</div>
</div>
</div> <!-- Fin columna izquierda -->
<!-- ========================================
COLUMNA DERECHA
======================================== -->
<div class="col-lg-6">
<!-- ========================================
GRUPO 5: SPACING
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-arrows-expand me-2" style="color: #FF8600;"></i>
Espaciado
</h5>
<div class="row g-2">
<div class="col-md-4">
<div class="form-group mb-3">
<label for="navbarPaddingVertical" class="text-secondary fw-medium mb-1">
Padding navbar (rem)
</label>
<input type="number"
id="navbarPaddingVertical"
class="form-control form-control-sm"
value="0.75"
min="0"
max="3"
step="0.05">
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label for="navbarLinkPaddingVertical" class="text-secondary fw-medium mb-1">
Padding links V (rem)
</label>
<input type="number"
id="navbarLinkPaddingVertical"
class="form-control form-control-sm"
value="0.5"
min="0"
max="2"
step="0.05">
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label for="navbarLinkPaddingHorizontal" class="text-secondary fw-medium mb-1">
Padding links H (rem)
</label>
<input type="number"
id="navbarLinkPaddingHorizontal"
class="form-control form-control-sm"
value="0.65"
min="0"
max="2"
step="0.05">
</div>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 6: LET'S TALK BUTTON
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-lightning-charge-fill me-2" style="color: #FF8600;"></i>
Botón "Let's Talk"
</h5>
<!-- Switches verticales -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarLetsTalkEnabled" checked="">
<label class="form-check-label small" for="navbarLetsTalkEnabled" style="color: #495057;">
<i class="bi bi-power me-1" style="color: #FF8600;"></i>
<strong>Mostrar botón</strong>
</label>
</div>
</div>
<div class="mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarLetsTalkShowIcon" checked="">
<label class="form-check-label small" for="navbarLetsTalkShowIcon" style="color: #495057;">
<i class="bi bi-eye me-1" style="color: #FF8600;"></i>
<strong>Mostrar icono</strong>
</label>
</div>
</div>
<!-- Texto e icono -->
<div class="row g-2">
<div class="col-6">
<div class="form-group mb-3">
<label for="navbarLetsTalkText" class="text-secondary fw-medium mb-1">
Texto del botón
</label>
<input type="text"
id="navbarLetsTalkText"
class="form-control form-control-sm"
value="Let's Talk"
maxlength="30"
placeholder="Let's Talk">
</div>
</div>
<div class="col-6">
<div class="form-group mb-3">
<label for="navbarLetsTalkIconClass" class="text-secondary fw-medium mb-1">
Clase del icono
</label>
<input type="text"
id="navbarLetsTalkIconClass"
class="form-control form-control-sm"
value="bi bi-lightning-charge-fill"
maxlength="50"
placeholder="bi bi-lightning-charge-fill">
</div>
</div>
</div>
<!-- Posición -->
<div class="form-group mb-0">
<label for="navbarLetsTalkPosition" class="text-secondary fw-medium mb-1">
Posición dentro del navbar
</label>
<select id="navbarLetsTalkPosition" class="form-select form-select-sm">
<option value="left">Izquierda</option>
<option value="center">Centro</option>
<option value="right" selected>Derecha</option>
</select>
</div>
</div>
</div>
<!-- ========================================
GRUPO 7: DROPDOWN
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-chevron-down me-2" style="color: #FF8600;"></i>
Dropdown
</h5>
<!-- Switch vertical -->
<div class="mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="navbarDropdownEnableHoverDesktop" checked="">
<label class="form-check-label small" for="navbarDropdownEnableHoverDesktop" style="color: #495057;">
<i class="bi bi-cursor me-1" style="color: #FF8600;"></i>
<strong>Activar al hover (desktop)</strong>
</label>
</div>
</div>
<!-- Números y selects -->
<div class="row g-2">
<div class="col-6">
<div class="form-group mb-3">
<label for="navbarDropdownMaxHeight" class="text-secondary fw-medium mb-1">
Altura máxima (vh)
</label>
<input type="number"
id="navbarDropdownMaxHeight"
class="form-control form-control-sm"
value="70"
min="30"
max="90">
</div>
</div>
<div class="col-6">
<div class="form-group mb-3">
<label for="navbarDropdownBorderRadius" class="text-secondary fw-medium mb-1">
Border radius (px)
</label>
<input type="number"
id="navbarDropdownBorderRadius"
class="form-control form-control-sm"
value="8"
min="0"
max="20">
</div>
</div>
</div>
<div class="row g-2">
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarDropdownItemPaddingVertical" class="text-secondary fw-medium mb-1">
Padding items V (rem)
</label>
<input type="number"
id="navbarDropdownItemPaddingVertical"
class="form-control form-control-sm"
value="0.5"
min="0"
max="2"
step="0.05">
</div>
</div>
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarDropdownItemPaddingHorizontal" class="text-secondary fw-medium mb-1">
Padding items H (rem)
</label>
<input type="number"
id="navbarDropdownItemPaddingHorizontal"
class="form-control form-control-sm"
value="1.25"
min="0"
max="3"
step="0.05">
</div>
</div>
</div>
</div>
</div>
<!-- ========================================
GRUPO 8: AVANZADO (OPCIONAL)
======================================== -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-gear me-2" style="color: #FF8600;"></i>
Avanzado
</h5>
<div class="row g-2">
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarZIndex" class="text-secondary fw-medium mb-1">
Z-index
</label>
<input type="number"
id="navbarZIndex"
class="form-control form-control-sm"
value="1030"
min="0"
max="9999">
</div>
</div>
<div class="col-6">
<div class="form-group mb-0">
<label for="navbarTransitionSpeed" class="text-secondary fw-medium mb-1">
Velocidad transiciones
</label>
<select id="navbarTransitionSpeed" class="form-select form-select-sm">
<option value="fast">Rápida (0.2s)</option>
<option value="normal" selected>Normal (0.3s)</option>
<option value="slow">Lenta (0.5s)</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div> <!-- Fin columna derecha -->
</div> <!-- Fin row g-3 -->
</div> <!-- Fin tab-pane -->

View File

@@ -1,237 +0,0 @@
<?php
/**
* Admin Component: Top Bar Configuration
*
* @package Apus_Theme
* @subpackage Admin_Panel
* @since 2.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
?>
<div class="tab-pane fade show active" id="topBarTab" role="tabpanel">
<!-- Header del Tab -->
<div class="rounded p-4 mb-4 shadow text-white" style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%); border-left: 4px solid #FF8600;">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div>
<h3 class="h4 mb-1 fw-bold">
<i class="bi bi-megaphone-fill me-2" style="color: #FF8600;"></i>
Configuración Top Bar
</h3>
<p class="mb-0 small" style="opacity: 0.85;">
Personaliza la barra de anuncios superior de tu sitio
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-light" id="resetTopBarDefaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- Grid: 2 columnas + 1 fila completa -->
<div class="row g-3">
<!-- COLUMNA IZQUIERDA -->
<div class="col-lg-6">
<!-- GRUPO 1: ACTIVACIÓN -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-toggle-on me-2" style="color: #FF8600;"></i>
Activación y Visibilidad
</h5>
<!-- Enabled -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="topBarEnabled" checked="">
<label class="form-check-label small" for="topBarEnabled" style="color: #495057;">
<i class="bi bi-power me-1" style="color: #FF8600;"></i>
<strong>Activar Top Bar</strong>
</label>
</div>
</div>
<!-- Show on Mobile -->
<div class="mb-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="topBarShowOnMobile" checked="">
<label class="form-check-label small" for="topBarShowOnMobile" style="color: #495057;">
<i class="bi bi-phone me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Mobile</strong> <span class="text-muted">(&lt;768px)</span>
</label>
</div>
</div>
<!-- Show on Desktop -->
<div class="mb-0">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="topBarShowOnDesktop" checked="">
<label class="form-check-label small" for="topBarShowOnDesktop" style="color: #495057;">
<i class="bi bi-display me-1" style="color: #FF8600;"></i>
<strong>Mostrar en Desktop</strong> <span class="text-muted">(≥768px)</span>
</label>
</div>
</div>
</div>
</div>
<!-- GRUPO 2: ESTILOS -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-palette me-2" style="color: #FF8600;"></i>
Estilos Personalizados
</h5>
<!-- 4 colores en grid 2x2 -->
<div class="row g-2 mb-2">
<div class="col-6">
<label for="topBarBgColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-paint-bucket me-1" style="color: #FF8600;"></i>
Color de fondo
</label>
<input type="color" id="topBarBgColor" class="form-control form-control-color w-100" value="#0E2337" title="Seleccionar color de fondo">
<small class="text-muted d-block mt-1" id="topBarBgColorValue">#0E2337</small>
</div>
<div class="col-6">
<label for="topBarTextColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-fonts me-1" style="color: #FF8600;"></i>
Color de texto
</label>
<input type="color" id="topBarTextColor" class="form-control form-control-color w-100" value="#ffffff" title="Seleccionar color de texto">
<small class="text-muted d-block mt-1" id="topBarTextColorValue">#FFFFFF</small>
</div>
<div class="col-6">
<label for="topBarHighlightColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-star me-1" style="color: #FF8600;"></i>
Color destacado
</label>
<input type="color" id="topBarHighlightColor" class="form-control form-control-color w-100" value="#FF8600" title="Seleccionar color destacado">
<small class="text-muted d-block mt-1" id="topBarHighlightColorValue">#FF8600</small>
</div>
<div class="col-6">
<label for="topBarLinkHoverColor" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-cursor me-1" style="color: #FF8600;"></i>
Hover enlace
</label>
<input type="color" id="topBarLinkHoverColor" class="form-control form-control-color w-100" value="#FF6B35" title="Seleccionar color hover del enlace">
<small class="text-muted d-block mt-1" id="topBarLinkHoverColorValue">#FF6B35</small>
</div>
</div>
<!-- Tamaño de fuente -->
<div class="mb-0">
<label for="topBarFontSize" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-type me-1" style="color: #FF8600;"></i>
Tamaño de fuente
</label>
<select id="topBarFontSize" class="form-select form-select-sm">
<option value="small">Pequeño (0.8rem)</option>
<option value="normal" selected="">Normal (0.9rem)</option>
<option value="large">Grande (1rem)</option>
</select>
</div>
</div>
</div>
</div>
<!-- COLUMNA DERECHA -->
<div class="col-lg-6">
<!-- GRUPO 3: CONTENIDO -->
<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">
<div class="card-body">
<h5 class="fw-bold mb-3" style="color: #1e3a5f;">
<i class="bi bi-card-text me-2" style="color: #FF8600;"></i>
Contenido y Mensajes
</h5>
<!-- Icono + mostrar -->
<div class="row g-2 mb-2">
<div class="col-8">
<label for="topBarIconClass" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-emoji-smile me-1" style="color: #FF8600;"></i>
Clase del icono <span class="badge bg-secondary" style="font-size: 0.65rem;">Bootstrap Icons</span>
</label>
<input type="text" id="topBarIconClass" class="form-control form-control-sm" placeholder="bi bi-megaphone-fill" value="bi bi-megaphone-fill" maxlength="50">
<small class="text-muted d-block mt-1">
<i class="bi bi-info-circle me-1"></i>
Ver: <a href="https://icons.getbootstrap.com/" target="_blank" class="text-decoration-none" style="color: #FF8600;">Bootstrap Icons <i class="bi bi-box-arrow-up-right"></i></a>
</small>
</div>
<div class="col-4">
<label class="form-label small mb-1 fw-semibold" style="color: #495057;">Opciones</label>
<div class="form-check form-switch mt-2">
<input class="form-check-input" type="checkbox" id="topBarShowIcon" checked="">
<label class="form-check-label small" for="topBarShowIcon" style="color: #495057;">Mostrar</label>
</div>
</div>
</div>
<!-- Texto destacado -->
<div class="mb-2">
<label for="topBarHighlightText" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-bookmark-star me-1" style="color: #FF8600;"></i>
Texto destacado <span class="badge text-dark" style="background-color: #FFB800; font-size: 0.65rem;">Opcional</span>
</label>
<input type="text" id="topBarHighlightText" class="form-control form-control-sm" placeholder="Ej: &quot;Nuevo:&quot; o &quot;Promoción:&quot;" value="Nuevo:" maxlength="30">
</div>
<!-- Mensaje principal -->
<div class="mb-2">
<label for="topBarMessageText" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-chat-left-text me-1" style="color: #FF8600;"></i>
Mensaje principal <span class="text-danger">*</span>
<span class="float-end text-muted"><span id="topBarMessageTextCount" class="fw-bold">77</span>/250</span>
</label>
<textarea id="topBarMessageText" class="form-control form-control-sm" rows="2" maxlength="250" placeholder="Ej: Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025." required="">Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.</textarea>
<div class="progress mt-1" style="height: 3px;">
<div id="topBarMessageTextProgress" class="progress-bar bg-orange-primary" role="progressbar" style="width: 30.8%; background-color: rgb(255, 134, 0);" aria-valuenow="77" aria-valuemin="0" aria-valuemax="250"></div>
</div>
</div>
<!-- Enlace (3 campos compactos) -->
<div class="row g-2 mb-2">
<div class="col-5">
<label for="topBarLinkText" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-link-45deg me-1" style="color: #FF8600;"></i>
Texto enlace
</label>
<input type="text" id="topBarLinkText" class="form-control form-control-sm" placeholder="Ver Catálogo" value="Ver Catálogo →" maxlength="50">
</div>
<div class="col-5">
<label for="topBarLinkUrl" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-globe me-1" style="color: #FF8600;"></i>
URL
</label>
<input type="url" id="topBarLinkUrl" class="form-control form-control-sm" placeholder="/catalogo" value="/catalogo">
</div>
<div class="col-2">
<label for="topBarLinkTarget" class="form-label small mb-1 fw-semibold" style="color: #495057;">
<i class="bi bi-window me-1" style="color: #FF8600;"></i>
Target
</label>
<select id="topBarLinkTarget" class="form-select form-select-sm">
<option value="_self" selected="">_self</option>
<option value="_blank">_blank</option>
</select>
</div>
</div>
<div class="mb-0">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="topBarShowLink" checked="">
<label class="form-check-label small" for="topBarShowLink" style="color: #495057;">
<strong>Mostrar enlace</strong>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -80,13 +80,6 @@ class APUS_Admin_Menu {
APUS_ADMIN_PANEL_VERSION
);
// Component: Navbar CSS (estilos admin específicos)
wp_enqueue_style(
'apus-component-navbar-css',
APUS_ADMIN_PANEL_URL . 'assets/css/component-navbar.css',
array('apus-admin-panel-css'),
APUS_ADMIN_PANEL_VERSION
);
// Bootstrap 5.3.2 JS
wp_enqueue_script(
@@ -106,20 +99,12 @@ class APUS_Admin_Menu {
true
);
// Component: Navbar JS (cargar antes de admin-app.js)
wp_enqueue_script(
'apus-component-navbar-js',
APUS_ADMIN_PANEL_URL . 'assets/js/component-navbar.js',
array('jquery'),
APUS_ADMIN_PANEL_VERSION,
true
);
// Admin Panel JS (Core - depende de componentes)
// Admin Panel JS (Core)
wp_enqueue_script(
'apus-admin-panel-js',
APUS_ADMIN_PANEL_URL . 'assets/js/admin-app.js',
array('jquery', 'axios', 'apus-component-navbar-js'),
array('jquery', 'axios'),
APUS_ADMIN_PANEL_VERSION,
true
);

View File

@@ -68,74 +68,27 @@ class APUS_Settings_Manager {
/**
* Valores por defecto
* NOTA: Aquí se agregan los defaults de cada componente
* NOTA: Los defaults se cargarán desde la tabla wp_apus_theme_components_defaults
*/
public function get_defaults() {
return array(
'version' => APUS_ADMIN_PANEL_VERSION,
'components' => array(
'top_bar' => array(
'enabled' => true,
'show_on_mobile' => true,
'show_on_desktop' => true,
'icon_class' => 'bi bi-megaphone-fill',
'show_icon' => true,
'highlight_text' => 'Nuevo:',
'message_text' => 'Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.',
'link_text' => 'Ver Catálogo',
'link_url' => '/catalogo',
'link_target' => '_self',
'show_link' => true,
'custom_styles' => array(
// Valores extraídos de componente-top-bar.css
'background_color' => '#0E2337', // var(--color-navy-dark)
'text_color' => '#ffffff',
'highlight_color' => '#FF8600', // var(--color-orange-primary)
'link_hover_color' => '#FF8600', // var(--color-orange-primary)
'font_size' => 'normal' // 0.9rem del CSS
)
)
// Navbar - Pendiente
// Hero - Pendiente
// Footer - Pendiente
// Los componentes se agregarán aquí cuando se ejecute el algoritmo
)
);
}
/**
* Sanitizar configuraciones
* NOTA: Aquí se agrega sanitización de cada componente
* NOTA: Los sanitizers de componentes se ejecutarán aquí cuando se implementen
*/
public function sanitize_settings($data) {
$sanitized = array(
'components' => array()
);
// Sanitizar Top Bar
if (isset($data['components']['top_bar'])) {
$top_bar = $data['components']['top_bar'];
$sanitized['components']['top_bar'] = array(
'enabled' => !empty($top_bar['enabled']),
'show_on_mobile' => !empty($top_bar['show_on_mobile']),
'show_on_desktop' => !empty($top_bar['show_on_desktop']),
'icon_class' => sanitize_text_field($top_bar['icon_class'] ?? ''),
'show_icon' => !empty($top_bar['show_icon']),
'highlight_text' => sanitize_text_field($top_bar['highlight_text'] ?? ''),
'message_text' => sanitize_text_field($top_bar['message_text'] ?? ''),
'link_text' => sanitize_text_field($top_bar['link_text'] ?? ''),
'link_url' => esc_url_raw($top_bar['link_url'] ?? ''),
'link_target' => in_array($top_bar['link_target'] ?? '', array('_self', '_blank')) ? $top_bar['link_target'] : '_self',
'show_link' => !empty($top_bar['show_link']),
'custom_styles' => array(
'background_color' => sanitize_hex_color($top_bar['custom_styles']['background_color'] ?? ''),
'text_color' => sanitize_hex_color($top_bar['custom_styles']['text_color'] ?? ''),
'highlight_color' => sanitize_hex_color($top_bar['custom_styles']['highlight_color'] ?? ''),
'link_hover_color' => sanitize_hex_color($top_bar['custom_styles']['link_hover_color'] ?? ''),
'font_size' => in_array($top_bar['custom_styles']['font_size'] ?? '', array('small', 'normal', 'large')) ? $top_bar['custom_styles']['font_size'] : 'normal'
)
);
}
// Los componentes se sanitizarán aquí cuando se ejecute el algoritmo
return $sanitized;
}

View File

@@ -16,6 +16,7 @@ class APUS_Validator {
/**
* Validar todas las configuraciones
* Los validators de componentes se ejecutarán aquí cuando se implementen
*/
public function validate($data) {
$errors = array();
@@ -26,81 +27,11 @@ class APUS_Validator {
return array('valid' => false, 'errors' => $errors);
}
// Validar Top Bar
if (isset($data['components']['top_bar'])) {
$top_bar_errors = $this->validate_top_bar($data['components']['top_bar']);
$errors = array_merge($errors, $top_bar_errors);
}
// Los componentes se validarán aquí cuando se ejecute el algoritmo
return array(
'valid' => empty($errors),
'errors' => $errors
);
}
/**
* Validar Top Bar
*/
public function validate_top_bar($top_bar) {
$errors = array();
// Validar icon_class
if (!empty($top_bar['icon_class']) && strlen($top_bar['icon_class']) > 50) {
$errors[] = 'La clase del icono no puede exceder 50 caracteres';
}
// Validar highlight_text
if (!empty($top_bar['highlight_text']) && strlen($top_bar['highlight_text']) > 30) {
$errors[] = 'El texto destacado no puede exceder 30 caracteres';
}
// Validar message_text
if (empty($top_bar['message_text'])) {
$errors[] = 'El mensaje principal es obligatorio';
} elseif (strlen($top_bar['message_text']) > 250) {
$errors[] = 'El mensaje principal no puede exceder 250 caracteres';
}
// Validar link_text
if (!empty($top_bar['link_text']) && strlen($top_bar['link_text']) > 50) {
$errors[] = 'El texto del enlace no puede exceder 50 caracteres';
}
// Validar link_url (acepta URLs completas y relativas que empiecen con /)
if (!empty($top_bar['link_url'])) {
$url = $top_bar['link_url'];
$is_valid_url = filter_var($url, FILTER_VALIDATE_URL) !== false;
$is_relative_url = preg_match('/^\//', $url);
if (!$is_valid_url && !$is_relative_url) {
$errors[] = 'La URL del enlace no es válida';
}
}
// Validar link_target
if (!in_array($top_bar['link_target'] ?? '', array('_self', '_blank'))) {
$errors[] = 'El target del enlace debe ser _self o _blank';
}
// Validar colores
if (!empty($top_bar['custom_styles']['background_color']) && !preg_match('/^#[a-f0-9]{6}$/i', $top_bar['custom_styles']['background_color'])) {
$errors[] = 'El color de fondo debe ser un color hexadecimal válido';
}
if (!empty($top_bar['custom_styles']['text_color']) && !preg_match('/^#[a-f0-9]{6}$/i', $top_bar['custom_styles']['text_color'])) {
$errors[] = 'El color de texto debe ser un color hexadecimal válido';
}
if (!empty($top_bar['custom_styles']['highlight_color']) && !preg_match('/^#[a-f0-9]{6}$/i', $top_bar['custom_styles']['highlight_color'])) {
$errors[] = 'El color del highlight debe ser un color hexadecimal válido';
}
if (!empty($top_bar['custom_styles']['link_hover_color']) && !preg_match('/^#[a-f0-9]{6}$/i', $top_bar['custom_styles']['link_hover_color'])) {
$errors[] = 'El color hover del enlace debe ser un color hexadecimal válido';
}
// Validar font_size
if (!in_array($top_bar['custom_styles']['font_size'] ?? '', array('small', 'normal', 'large'))) {
$errors[] = 'El tamaño de fuente debe ser small, normal o large';
}
return $errors;
}
}

View File

@@ -1,173 +0,0 @@
<?php
/**
* Hero Section Sanitizer
*
* Sanitiza configuraciones del componente Hero Section
*
* @package Apus_Theme
* @subpackage Admin_Panel\Sanitizers
* @since 2.1.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class APUS_HeroSection_Sanitizer
*
* Sanitiza todas las configuraciones del componente Hero Section
*/
class APUS_HeroSection_Sanitizer {
/**
* Obtiene los valores por defecto del Hero Section
*
* @return array Valores por defecto
* @since 2.1.0
*/
public function get_defaults() {
return array(
// Activación y Visibilidad
'enabled' => true,
'show_on_mobile' => true,
'show_on_desktop' => true,
// Contenido y Estructura
'show_category_badges' => true,
'category_badge_icon' => 'bi bi-folder-fill',
'excluded_categories' => array('Uncategorized', 'Sin categoría'),
'title_alignment' => 'center',
'title_display_class' => 'display-5',
// Colores del Hero
'use_gradient_background' => true,
'gradient_start_color' => '#1e3a5f',
'gradient_end_color' => '#2c5282',
'gradient_angle' => 135,
'hero_text_color' => '#ffffff',
'solid_background_color' => '#1e3a5f',
// Colores de Category Badges
'badge_bg_color' => 'rgba(255, 255, 255, 0.15)',
'badge_bg_hover_color' => 'rgba(255, 133, 0, 0.2)',
'badge_border_color' => 'rgba(255, 255, 255, 0.2)',
'badge_text_color' => 'rgba(255, 255, 255, 0.95)',
'badge_icon_color' => '#FFB800',
// Espaciado y Dimensiones
'hero_padding_vertical' => 3.0,
'hero_padding_horizontal' => 0.0,
'hero_margin_bottom' => 1.5,
'badges_gap' => 0.5,
'badge_padding_vertical' => 0.375,
'badge_padding_horizontal' => 0.875,
'badge_border_radius' => 20,
// Tipografía
'h1_font_weight' => 700,
'badge_font_size' => 0.813,
'badge_font_weight' => 500,
'h1_line_height' => 1.4,
// Efectos Visuales
'enable_h1_text_shadow' => true,
'h1_text_shadow' => '1px 1px 2px rgba(0, 0, 0, 0.2)',
'enable_hero_box_shadow' => true,
'hero_box_shadow' => '0 4px 16px rgba(30, 58, 95, 0.25)',
'enable_badge_backdrop_filter' => true,
'badge_backdrop_filter' => 'blur(10px)',
// Transiciones y Animaciones
'badge_transition_speed' => 'normal',
'badge_hover_effect' => 'background',
// Avanzado
'custom_hero_classes' => '',
'custom_badge_classes' => ''
);
}
/**
* Sanitiza los datos del Hero Section
*
* @param array $data Datos sin sanitizar del Hero Section
* @return array Datos sanitizados
*/
public function sanitize($data) {
return array_merge(
// Activación y Visibilidad - Booleanos
APUS_Sanitizer_Helper::sanitize_booleans($data, array(
'enabled', 'show_on_mobile', 'show_on_desktop', 'show_category_badges',
'use_gradient_background', 'enable_h1_text_shadow', 'enable_hero_box_shadow',
'enable_badge_backdrop_filter'
)),
// Contenido y Estructura - Textos
APUS_Sanitizer_Helper::sanitize_texts($data, array(
'category_badge_icon' => 'bi bi-folder-fill',
'title_display_class' => 'display-5',
'h1_text_shadow' => '1px 1px 2px rgba(0, 0, 0, 0.2)',
'hero_box_shadow' => '0 4px 16px rgba(30, 58, 95, 0.25)',
'badge_backdrop_filter' => 'blur(10px)',
'custom_hero_classes' => '',
'custom_badge_classes' => ''
)),
// Colores de Category Badges - RGBA strings (text)
array(
'badge_bg_color' => APUS_Sanitizer_Helper::sanitize_text($data, 'badge_bg_color', 'rgba(255, 255, 255, 0.15)'),
'badge_bg_hover_color' => APUS_Sanitizer_Helper::sanitize_text($data, 'badge_bg_hover_color', 'rgba(255, 133, 0, 0.2)'),
'badge_border_color' => APUS_Sanitizer_Helper::sanitize_text($data, 'badge_border_color', 'rgba(255, 255, 255, 0.2)'),
'badge_text_color' => APUS_Sanitizer_Helper::sanitize_text($data, 'badge_text_color', 'rgba(255, 255, 255, 0.95)')
),
// Colores del Hero - Hex colors
array(
'gradient_start_color' => APUS_Sanitizer_Helper::sanitize_color($data, 'gradient_start_color', '#1e3a5f'),
'gradient_end_color' => APUS_Sanitizer_Helper::sanitize_color($data, 'gradient_end_color', '#2c5282'),
'hero_text_color' => APUS_Sanitizer_Helper::sanitize_color($data, 'hero_text_color', '#ffffff'),
'solid_background_color' => APUS_Sanitizer_Helper::sanitize_color($data, 'solid_background_color', '#1e3a5f'),
'badge_icon_color' => APUS_Sanitizer_Helper::sanitize_color($data, 'badge_icon_color', '#FFB800')
),
// Enums
APUS_Sanitizer_Helper::sanitize_enums($data, array(
'title_alignment' => array('allowed' => array('left', 'center', 'right'), 'default' => 'center'),
'badge_transition_speed' => array('allowed' => array('fast', 'normal', 'slow'), 'default' => 'normal'),
'badge_hover_effect' => array('allowed' => array('none', 'background', 'scale', 'brightness'), 'default' => 'background')
)),
// Enteros
APUS_Sanitizer_Helper::sanitize_ints($data, array(
'gradient_angle' => 135,
'badge_border_radius' => 20
)),
// Enteros en arrays (h1_font_weight, badge_font_weight)
array(
'h1_font_weight' => APUS_Sanitizer_Helper::sanitize_enum($data, 'h1_font_weight', array(400, 500, 600, 700), 700),
'badge_font_weight' => APUS_Sanitizer_Helper::sanitize_enum($data, 'badge_font_weight', array(400, 500, 600, 700), 500)
),
// Floats
APUS_Sanitizer_Helper::sanitize_floats($data, array(
'hero_padding_vertical' => 3.0,
'hero_padding_horizontal' => 0.0,
'hero_margin_bottom' => 1.5,
'badges_gap' => 0.5,
'badge_padding_vertical' => 0.375,
'badge_padding_horizontal' => 0.875,
'badge_font_size' => 0.813,
'h1_line_height' => 1.4
)),
// Array de strings
array('excluded_categories' => APUS_Sanitizer_Helper::sanitize_array_of_strings(
$data,
'excluded_categories',
array('Uncategorized', 'Sin categoría')
))
);
}
}

View File

@@ -1,99 +0,0 @@
<?php
/**
* Let's Talk Button Sanitizer
*
* Sanitiza configuraciones del componente Let's Talk Button
*
* @package Apus_Theme
* @subpackage Admin_Panel\Sanitizers
* @since 2.1.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class APUS_LetsTalkButton_Sanitizer
*
* Sanitiza todas las configuraciones del componente Let's Talk Button
*/
class APUS_LetsTalkButton_Sanitizer {
/**
* Obtiene los valores por defecto del Let's Talk Button
*
* @return array Valores por defecto
* @since 2.1.0
*/
public function get_defaults() {
return array(
'enabled' => true,
'text' => "Let's Talk",
'icon_class' => 'bi bi-lightning-charge-fill',
'show_icon' => true,
'position' => 'right',
'enable_box_shadow' => false,
'hover_effect' => 'none',
'modal_target' => '#contactModal',
'custom_styles' => array(
'background_color' => '#FF8600',
'background_hover_color' => '#FF6B35',
'text_color' => '#ffffff',
'icon_color' => '#ffffff',
'font_weight' => '600',
'padding_vertical' => 0.5,
'padding_horizontal' => 1.5,
'border_radius' => 6,
'border_width' => 0,
'border_color' => '',
'border_style' => 'solid',
'transition_speed' => 'normal',
'box_shadow' => '0 2px 8px rgba(0, 0, 0, 0.15)'
)
);
}
/**
* Sanitiza los datos del Let's Talk Button
*
* @param array $data Datos sin sanitizar del Let's Talk Button
* @return array Datos sanitizados
*/
public function sanitize($data) {
return array_merge(
// Booleanos
APUS_Sanitizer_Helper::sanitize_booleans($data, array(
'enabled', 'show_icon', 'enable_box_shadow'
)),
// Textos
APUS_Sanitizer_Helper::sanitize_texts($data, array(
'text', 'icon_class', 'modal_target'
)),
// Enums
APUS_Sanitizer_Helper::sanitize_enums($data, array(
'position' => array('allowed' => array('left', 'center', 'right'), 'default' => 'right'),
'hover_effect' => array('allowed' => array('none', 'scale', 'brightness'), 'default' => 'none')
)),
// Custom styles anidado
array('custom_styles' => APUS_Sanitizer_Helper::sanitize_nested_group($data, 'custom_styles', array(
'background_color' => array('type' => 'color', 'default' => ''),
'background_hover_color' => array('type' => 'color', 'default' => ''),
'text_color' => array('type' => 'color', 'default' => ''),
'icon_color' => array('type' => 'color', 'default' => ''),
'font_weight' => array('type' => 'text', 'default' => ''),
'padding_vertical' => array('type' => 'float', 'default' => 0.0),
'padding_horizontal' => array('type' => 'float', 'default' => 0.0),
'border_radius' => array('type' => 'int', 'default' => 0),
'border_width' => array('type' => 'int', 'default' => 0),
'border_color' => array('type' => 'color', 'default' => ''),
'border_style' => array('type' => 'enum', 'allowed' => array('solid', 'dashed', 'dotted'), 'default' => 'solid'),
'transition_speed' => array('type' => 'enum', 'allowed' => array('fast', 'normal', 'slow'), 'default' => 'normal'),
'box_shadow' => array('type' => 'text', 'default' => '')
)))
);
}
}

View File

@@ -1,136 +0,0 @@
<?php
/**
* Navbar Sanitizer
*
* Sanitiza configuraciones del componente Navbar
*
* @package Apus_Theme
* @subpackage Admin_Panel\Sanitizers
* @since 2.1.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class APUS_Navbar_Sanitizer
*
* Sanitiza todas las configuraciones del componente Navbar
*/
class APUS_Navbar_Sanitizer {
/**
* Obtiene los valores por defecto del Navbar
*
* @return array Valores por defecto
* @since 2.1.0
*/
public function get_defaults() {
return array(
'enabled' => true,
'show_on_mobile' => true,
'show_on_desktop' => true,
'position' => 'sticky',
'responsive_breakpoint' => 'lg',
'enable_box_shadow' => true,
'enable_underline_effect' => true,
'enable_hover_background' => true,
'lets_talk_button' => array(
'enabled' => true,
'text' => "Let's Talk",
'icon_class' => 'bi bi-lightning-charge-fill',
'show_icon' => true,
'position' => 'right'
),
'dropdown' => array(
'enable_hover_desktop' => true,
'max_height' => 70,
'border_radius' => 8,
'item_padding_vertical' => 0.5,
'item_padding_horizontal' => 1.25
),
'custom_styles' => array(
'background_color' => '#1e3a5f',
'text_color' => '#ffffff',
'link_hover_color' => '#FF8600',
'link_hover_bg_color' => '#FF8600',
'dropdown_bg_color' => '#ffffff',
'dropdown_item_color' => '#4A5568',
'dropdown_item_hover_color' => '#FF8600',
'font_size' => 'normal',
'font_weight' => '500',
'box_shadow_intensity' => 'normal',
'border_radius' => 4,
'padding_vertical' => 0.75,
'link_padding_vertical' => 0.5,
'link_padding_horizontal' => 0.65,
'z_index' => 1030,
'transition_speed' => 'normal'
)
);
}
/**
* Sanitiza los datos del Navbar
*
* @param array $data Datos sin sanitizar del Navbar
* @return array Datos sanitizados
*/
public function sanitize($data) {
return array_merge(
// Booleanos principales
APUS_Sanitizer_Helper::sanitize_booleans($data, array(
'enabled', 'show_on_mobile', 'show_on_desktop',
'enable_box_shadow', 'enable_underline_effect', 'enable_hover_background'
)),
// Enums principales
APUS_Sanitizer_Helper::sanitize_enums($data, array(
'position' => array('allowed' => array('sticky', 'static', 'fixed'), 'default' => 'sticky'),
'responsive_breakpoint' => array('allowed' => array('sm', 'md', 'lg', 'xl', 'xxl'), 'default' => 'lg')
)),
// Let's Talk Button anidado
array('lets_talk_button' => APUS_Sanitizer_Helper::sanitize_nested_group($data, 'lets_talk_button', array(
'enabled' => array('type' => 'bool'),
'text' => array('type' => 'text', 'default' => ''),
'icon_class' => array('type' => 'text', 'default' => ''),
'show_icon' => array('type' => 'bool'),
'position' => array('type' => 'enum', 'allowed' => array('left', 'center', 'right'), 'default' => 'right')
))),
// Dropdown anidado
array('dropdown' => APUS_Sanitizer_Helper::sanitize_nested_group($data, 'dropdown', array(
'enable_hover_desktop' => array('type' => 'bool'),
'max_height' => array('type' => 'int', 'default' => 70),
'border_radius' => array('type' => 'int', 'default' => 8),
'item_padding_vertical' => array('type' => 'float', 'default' => 0.5),
'item_padding_horizontal' => array('type' => 'float', 'default' => 1.25)
))),
// Custom styles anidado
array('custom_styles' => APUS_Sanitizer_Helper::sanitize_nested_group($data, 'custom_styles', array(
'background_color' => array('type' => 'color', 'default' => ''),
'text_color' => array('type' => 'color', 'default' => ''),
'link_hover_color' => array('type' => 'color', 'default' => ''),
'link_hover_bg_color' => array('type' => 'color', 'default' => ''),
'dropdown_bg_color' => array('type' => 'color', 'default' => ''),
'dropdown_item_color' => array('type' => 'color', 'default' => ''),
'dropdown_item_hover_color' => array('type' => 'color', 'default' => ''),
'font_size' => array('type' => 'enum', 'allowed' => array('small', 'normal', 'large'), 'default' => 'normal'),
'font_weight' => array('type' => 'enum', 'allowed' => array('400', '500', '600', '700'), 'default' => '500'),
'box_shadow_intensity' => array('type' => 'enum', 'allowed' => array('none', 'light', 'normal', 'strong'), 'default' => 'normal'),
'border_radius' => array('type' => 'int', 'default' => 4),
'padding_vertical' => array('type' => 'float', 'default' => 0.75),
'link_padding_vertical' => array('type' => 'float', 'default' => 0.5),
'link_padding_horizontal' => array('type' => 'float', 'default' => 0.65),
'z_index' => array('type' => 'int', 'default' => 1030),
'transition_speed' => array('type' => 'enum', 'allowed' => array('fast', 'normal', 'slow'), 'default' => 'normal')
)))
);
}
}

View File

@@ -1,88 +0,0 @@
<?php
/**
* Top Bar Sanitizer
*
* Sanitiza configuraciones del componente Top Bar
*
* @package Apus_Theme
* @subpackage Admin_Panel\Sanitizers
* @since 2.1.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class APUS_TopBar_Sanitizer
*
* Sanitiza todas las configuraciones del componente Top Bar
*/
class APUS_TopBar_Sanitizer {
/**
* Obtiene los valores por defecto del Top Bar
*
* @return array Valores por defecto
* @since 2.1.0
*/
public function get_defaults() {
return array(
'enabled' => true,
'show_on_mobile' => true,
'show_on_desktop' => true,
'icon_class' => 'bi bi-megaphone-fill',
'show_icon' => true,
'highlight_text' => 'Nuevo:',
'message_text' => 'Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.',
'link_text' => 'Ver Catálogo',
'link_url' => '/catalogo',
'link_target' => '_self',
'show_link' => true,
'custom_styles' => array(
'background_color' => '#0E2337',
'text_color' => '#ffffff',
'highlight_color' => '#FF8600',
'link_hover_color' => '#FF8600',
'font_size' => 'normal'
)
);
}
/**
* Sanitiza los datos del Top Bar
*
* @param array $data Datos sin sanitizar del Top Bar
* @return array Datos sanitizados
*/
public function sanitize($data) {
return array_merge(
// Booleanos
APUS_Sanitizer_Helper::sanitize_booleans($data, array(
'enabled', 'show_on_mobile', 'show_on_desktop', 'show_icon', 'show_link'
)),
// Textos
APUS_Sanitizer_Helper::sanitize_texts($data, array(
'icon_class', 'highlight_text', 'message_text', 'link_text'
)),
// URL
array('link_url' => APUS_Sanitizer_Helper::sanitize_url($data, 'link_url')),
// Enum
array('link_target' => APUS_Sanitizer_Helper::sanitize_enum(
$data, 'link_target', array('_self', '_blank'), '_self'
)),
// Custom styles anidado
array('custom_styles' => APUS_Sanitizer_Helper::sanitize_nested_group($data, 'custom_styles', array(
'background_color' => array('type' => 'color', 'default' => ''),
'text_color' => array('type' => 'color', 'default' => ''),
'highlight_color' => array('type' => 'color', 'default' => ''),
'link_hover_color' => array('type' => 'color', 'default' => ''),
'font_size' => array('type' => 'enum', 'allowed' => array('small', 'normal', 'large'), 'default' => 'normal')
)))
);
}
}

View File

@@ -19,505 +19,12 @@ if (!defined('ABSPATH')) {
<!-- Navigation Tabs -->
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" data-bs-target="#topBarTab" href="#topBarTab" role="tab">
<i class="bi bi-megaphone-fill me-2"></i>
Top Bar
</a>
</li>
<!-- Más tabs aquí: Navbar, Hero, Footer, etc. -->
<!-- Tabs de componentes se generarán aquí cuando se ejecute el algoritmo -->
</ul>
<!-- Tab Content -->
<div class="tab-content mt-3">
<!-- ============================= -->
<!-- TAB: TOP BAR - VERSIÓN MEJORADA -->
<!-- ============================= -->
<div id="topBarTab" class="tab-pane fade show active" role="tabpanel">
<!-- Header del Tab -->
<div class="tab-header mb-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h3 class="mb-1 text-navy-primary">
<i class="bi bi-megaphone-fill me-2 text-orange-primary"></i>
Configuración Top Bar
</h3>
<p class="text-neutral-600 mb-0">
Personaliza la barra de anuncios superior de tu sitio
</p>
</div>
<button type="button" class="btn btn-sm btn-outline-secondary" id="resetTopBarDefaults">
<i class="bi bi-arrow-counterclockwise me-1"></i>
Restaurar valores por defecto
</button>
</div>
</div>
<!-- Row para 2 cards por fila -->
<div class="row">
<!-- ============================= -->
<!-- GRUPO 1: ACTIVACIÓN -->
<!-- ============================= -->
<div class="col-md-6">
<div class="form-section card shadow-sm border-0 mb-4 h-100">
<div class="card-body">
<h4 class="section-title">
<span class="title-icon">
<i class="bi bi-toggle-on"></i>
</span>
Activación y Visibilidad
</h4>
<!-- Enabled -->
<div class="mb-4">
<label class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-power text-orange-primary me-1"></i>
Estado del Componente
</label>
<div class="toggle-container">
<div class="form-check form-switch form-switch-lg">
<input class="form-check-input"
type="checkbox"
id="topBarEnabled"
role="switch"
checked>
<label class="form-check-label" for="topBarEnabled">
Activar Top Bar
</label>
</div>
<small class="form-text text-neutral-700 d-block mt-2">
Activa o desactiva el Top Bar en todo el sitio
</small>
</div>
</div>
<!-- Show on Mobile -->
<div class="mb-4">
<label class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-phone text-orange-primary me-1"></i>
Visibilidad Mobile
</label>
<div class="toggle-container">
<div class="form-check form-switch form-switch-lg">
<input class="form-check-input"
type="checkbox"
id="topBarShowOnMobile"
role="switch"
checked>
<label class="form-check-label" for="topBarShowOnMobile">
Mostrar en dispositivos móviles
</label>
</div>
<small class="form-text text-neutral-700 d-block mt-2">
Pantallas menores a 768px
</small>
</div>
</div>
<!-- Show on Desktop -->
<div class="mb-0">
<label class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-display text-orange-primary me-1"></i>
Visibilidad Desktop
</label>
<div class="toggle-container">
<div class="form-check form-switch form-switch-lg">
<input class="form-check-input"
type="checkbox"
id="topBarShowOnDesktop"
role="switch"
checked>
<label class="form-check-label" for="topBarShowOnDesktop">
Mostrar en desktop
</label>
</div>
<small class="form-text text-neutral-700 d-block mt-2">
Pantallas de 768px en adelante
</small>
</div>
</div>
</div>
</div>
<div class="row">
<!-- ============================= -->
<!-- GRUPO 2: CONTENIDO -->
<!-- ============================= -->
<div class="col-md-6">
<div class="form-section card shadow-sm border-0 mb-4 h-100">
<div class="card-body">
<h4 class="section-title">
<span class="title-icon">
<i class="bi bi-card-text"></i>
</span>
Contenido y Mensajes
</h4>
<!-- Icono -->
<div class="row g-4 mb-4">
<div class="col-md-8">
<div class="form-group">
<label for="topBarIconClass" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-emoji-smile text-orange-primary me-1"></i>
Clase del icono
<span class="badge bg-neutral-100 text-neutral-600 ms-2">Bootstrap Icons</span>
</label>
<div class="input-group input-group-merge">
<span class="input-group-text bg-neutral-50 border-end-0">
<i class="bi bi-code-slash text-neutral-600"></i>
</span>
<input type="text"
id="topBarIconClass"
class="form-control border-start-0 ps-0"
placeholder="Ej: bi bi-megaphone-fill"
maxlength="50"
value="bi bi-megaphone-fill">
</div>
<small class="form-text text-neutral-700 d-flex align-items-center mt-2">
<i class="bi bi-info-circle me-1"></i>
Ver iconos disponibles:
<a href="https://icons.getbootstrap.com/" target="_blank" class="ms-1 text-orange-primary">
Bootstrap Icons <i class="bi bi-box-arrow-up-right ms-1"></i>
</a>
</small>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="form-label text-neutral-700 fw-medium mb-3">
Opciones de Icono
</label>
<div class="toggle-container">
<div class="form-check form-switch form-switch-lg">
<input class="form-check-input"
type="checkbox"
id="topBarShowIcon"
role="switch"
checked>
<label class="form-check-label" for="topBarShowIcon">
Mostrar icono
</label>
</div>
</div>
</div>
</div>
</div>
<!-- Texto destacado -->
<div class="row g-4 mb-4">
<div class="col-md-12">
<div class="form-group">
<label for="topBarHighlightText" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-bookmark-star text-orange-primary me-1"></i>
Texto destacado
<span class="badge bg-warning-subtle text-warning-emphasis ms-2">Opcional</span>
</label>
<input type="text"
id="topBarHighlightText"
class="form-control form-control-lg"
placeholder='Ej: "Nuevo:" o "Promoción:"'
maxlength="30"
value="Nuevo:">
<small class="form-text text-neutral-700 d-flex align-items-center mt-2">
<i class="bi bi-lightbulb text-warning me-1"></i>
Se muestra en <strong class="mx-1">negritas</strong> y con <span class="text-orange-primary fw-bold mx-1">color destacado</span>. Dejar vacío para omitir.
</small>
</div>
</div>
</div>
<!-- Mensaje principal -->
<div class="row g-4 mb-4">
<div class="col-md-12">
<div class="form-group">
<label for="topBarMessageText" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-chat-left-text text-orange-primary me-1"></i>
Mensaje principal
<span class="badge bg-danger-subtle text-danger-emphasis ms-2">Requerido</span>
</label>
<textarea id="topBarMessageText"
class="form-control form-control-lg"
rows="3"
maxlength="250"
placeholder="Ej: Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025."
required>Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.</textarea>
<div class="d-flex justify-content-between align-items-center mt-2">
<small class="form-text text-neutral-700">
<i class="bi bi-info-circle me-1"></i>
Mensaje que se mostrará en la barra superior
</small>
<small class="form-text">
<span id="topBarMessageTextCount" class="fw-bold">75</span><span class="text-neutral-600">/250 caracteres</span>
</small>
</div>
<div class="progress mt-2" style="height: 4px;">
<div id="topBarMessageTextProgress"
class="progress-bar bg-orange-primary"
role="progressbar"
style="width: 30%"
aria-valuenow="75"
aria-valuemin="0"
aria-valuemax="250"></div>
</div>
</div>
</div>
</div>
<!-- Enlace -->
<div class="row g-4">
<div class="col-md-5">
<div class="form-group">
<label for="topBarLinkText" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-link-45deg text-orange-primary me-1"></i>
Texto del enlace
</label>
<input type="text"
id="topBarLinkText"
class="form-control"
placeholder="Ej: Ver Catálogo"
maxlength="50"
value="Ver Catálogo →">
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="topBarLinkUrl" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-globe text-orange-primary me-1"></i>
URL del enlace
</label>
<input type="url"
id="topBarLinkUrl"
class="form-control"
placeholder="Ej: /catalogo o https://ejemplo.com"
value="/catalogo">
<small class="form-text text-neutral-700 mt-2 d-block">
URLs relativas (/page) o absolutas (https://...)
</small>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label for="topBarLinkTarget" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-window text-orange-primary me-1"></i>
Target
</label>
<select id="topBarLinkTarget" class="form-select">
<option value="_self" selected>Misma ventana</option>
<option value="_blank">Nueva ventana</option>
</select>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<div class="toggle-container">
<div class="form-check form-switch form-switch-lg">
<input class="form-check-input"
type="checkbox"
id="topBarShowLink"
role="switch"
checked>
<label class="form-check-label" for="topBarShowLink">
<strong>Mostrar enlace</strong>
<span class="text-neutral-700 ms-2">- Activa para incluir un botón de acción</span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Row para segunda fila de cards -->
<div class="row">
<!-- ============================= -->
<!-- GRUPO 3: ESTILOS AVANZADOS -->
<!-- ============================= -->
<div class="col-md-6">
<div class="form-section card shadow-sm border-0 mb-4 h-100">
<div class="card-body">
<h4 class="section-title">
<span class="title-icon">
<i class="bi bi-palette"></i>
</span>
Estilos Personalizados
</h4>
<!-- Colores (4 en una fila) -->
<div class="row g-4 mb-4">
<div class="col-md-3">
<div class="form-group">
<label for="topBarBgColor" class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-paint-bucket text-orange-primary me-1"></i>
Color de fondo
</label>
<div class="color-picker-wrapper">
<input type="color"
id="topBarBgColor"
class="form-control form-control-color"
value="#0E2337"
title="Seleccionar color de fondo">
<div class="color-preview-text mt-2">
<code class="text-neutral-600 small">#0E2337</code>
<small class="text-neutral-700 d-block">Navy Dark (Default)</small>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="topBarTextColor" class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-fonts text-orange-primary me-1"></i>
Color de texto
</label>
<div class="color-picker-wrapper">
<input type="color"
id="topBarTextColor"
class="form-control form-control-color"
value="#ffffff"
title="Seleccionar color de texto">
<div class="color-preview-text mt-2">
<code class="text-neutral-600 small">#ffffff</code>
<small class="text-neutral-700 d-block">White (Default)</small>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="topBarHighlightColor" class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-star text-orange-primary me-1"></i>
Color destacado
</label>
<div class="color-picker-wrapper">
<input type="color"
id="topBarHighlightColor"
class="form-control form-control-color"
value="#FF8600"
title="Seleccionar color destacado">
<div class="color-preview-text mt-2">
<code class="text-neutral-600 small">#FF8600</code>
<small class="text-neutral-700 d-block">Orange Primary (Default)</small>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="topBarLinkHoverColor" class="form-label text-neutral-700 fw-medium mb-3">
<i class="bi bi-cursor text-orange-primary me-1"></i>
Hover enlace
</label>
<div class="color-picker-wrapper">
<input type="color"
id="topBarLinkHoverColor"
class="form-control form-control-color"
value="#FF6B35"
title="Seleccionar color hover del enlace">
<div class="color-preview-text mt-2">
<code class="text-neutral-600 small">#FF6B35</code>
<small class="text-neutral-700 d-block">Orange Hover (Default)</small>
</div>
</div>
</div>
</div>
</div>
<!-- Tamaño de fuente -->
<div class="row g-4">
<div class="col-md-4">
<div class="form-group">
<label for="topBarFontSize" class="form-label text-neutral-700 fw-medium">
<i class="bi bi-type text-orange-primary me-1"></i>
Tamaño de fuente
</label>
<select id="topBarFontSize" class="form-select form-select-lg">
<option value="small">
Pequeño - 0.8rem (ideal para mucho texto)
</option>
<option value="normal" selected>
Normal - 0.9rem (recomendado)
</option>
<option value="large">
Grande - 1rem (máxima legibilidad)
</option>
</select>
<small class="form-text text-neutral-700 d-block mt-2">
<i class="bi bi-info-circle me-1"></i>
El tamaño afecta la altura total de la barra
</small>
</div>
</div>
<div class="col-md-8">
<div class="alert alert-info-custom d-flex align-items-start" role="alert">
<i class="bi bi-lightbulb-fill text-orange-primary me-3 fs-4"></i>
<div>
<h6 class="alert-heading mb-1">Tip de Diseño</h6>
<p class="mb-0 small">
Para mejor legibilidad, usa <strong>fondos oscuros</strong> (Navy Dark) con <strong>texto claro</strong> (White)
y <strong>acentos naranjas</strong> para las acciones importantes.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ============================= -->
<!-- VISTA PREVIA INTERACTIVA -->
<!-- ============================= -->
<div class="col-md-6">
<div class="form-section card shadow-sm border-0 mb-4 bg-neutral-50 h-100">
<div class="card-body">
<h4 class="section-title">
<span class="title-icon">
<i class="bi bi-eye"></i>
</span>
Vista Previa en Tiempo Real
</h4>
<div class="preview-container border border-2 border-neutral-100 rounded-3 p-4 bg-white">
<!-- Top Bar Preview -->
<div id="topBarPreview" class="top-bar-preview" style="background-color: #0E2337; color: #ffffff; padding: 12px 20px; border-radius: 8px; display: flex; align-items: center; justify-content: center; gap: 15px; flex-wrap: wrap;">
<i class="bi bi-megaphone-fill" style="font-size: 1.2rem; color: #FF8600;"></i>
<span style="font-weight: 700; color: #FF8600;">Nuevo:</span>
<span style="flex: 1; min-width: 300px; text-align: center;">Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.</span>
<a href="#" style="color: #ffffff; text-decoration: underline; white-space: nowrap; transition: color 0.3s;">Ver Catálogo →</a>
</div>
<div class="text-center mt-4">
<small class="text-neutral-700">
<i class="bi bi-info-circle me-1"></i>
La vista previa se actualiza automáticamente al modificar los campos
</small>
</div>
</div>
<div class="mt-4 d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-outline-secondary">
<i class="bi bi-phone me-1"></i>
Ver en Mobile
</button>
<button type="button" class="btn btn-outline-secondary">
<i class="bi bi-display me-1"></i>
Ver en Desktop
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Contenido de tabs de componentes se generará aquí cuando se ejecute el algoritmo -->
</div>
<!-- Action Buttons -->

View File

@@ -20,98 +20,7 @@
<body <?php body_class(); ?> data-bs-spy="scroll" data-bs-target=".toc-container" data-bs-offset="100">
<?php wp_body_open(); ?>
<!-- Top Notification Bar (Configurable desde Admin Panel) -->
<?php
// Obtener configuración del Top Bar
$settings = get_option('apus_theme_settings', array());
$top_bar_defaults = array(
'enabled' => true,
'show_on_mobile' => true,
'show_on_desktop' => true,
'icon_class' => 'bi bi-megaphone-fill',
'show_icon' => true,
'highlight_text' => 'Nuevo:',
'message_text' => 'Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.',
'link_text' => 'Ver Catálogo',
'link_url' => '/catalogo',
'link_target' => '_self',
'show_link' => true,
'custom_styles' => array(
'background_color' => '',
'text_color' => '',
'highlight_color' => '',
'link_hover_color' => '',
'font_size' => 'normal'
)
);
$top_bar_config = isset($settings['components']['top_bar']) ? $settings['components']['top_bar'] : array();
$top_bar = wp_parse_args($top_bar_config, $top_bar_defaults);
// Verificar si está habilitado
if ($top_bar['enabled']):
// Construir clases CSS
$classes = array('top-notification-bar');
if (!$top_bar['show_on_mobile']) {
$classes[] = 'd-none';
$classes[] = 'd-md-block';
}
if (!$top_bar['show_on_desktop']) {
$classes[] = 'd-md-none';
}
$class_attr = implode(' ', $classes);
// Construir estilos inline
$inline_styles = array();
if (!empty($top_bar['custom_styles']['background_color'])) {
$inline_styles[] = 'background-color: ' . esc_attr($top_bar['custom_styles']['background_color']);
}
if (!empty($top_bar['custom_styles']['text_color'])) {
$inline_styles[] = 'color: ' . esc_attr($top_bar['custom_styles']['text_color']);
}
// Font size
$font_size_map = array(
'small' => '0.8rem',
'normal' => '0.9rem',
'large' => '1rem'
);
if (isset($font_size_map[$top_bar['custom_styles']['font_size']])) {
$inline_styles[] = 'font-size: ' . $font_size_map[$top_bar['custom_styles']['font_size']];
}
$style_attr = !empty($inline_styles) ? ' style="' . implode('; ', $inline_styles) . '"' : '';
?>
<div class="<?php echo esc_attr($class_attr); ?>"<?php echo $style_attr; ?>>
<div class="container">
<div class="d-flex align-items-center justify-content-center">
<?php if ($top_bar['show_icon'] && !empty($top_bar['icon_class'])): ?>
<i class="<?php echo esc_attr($top_bar['icon_class']); ?> me-2"></i>
<?php endif; ?>
<span>
<?php if (!empty($top_bar['highlight_text'])): ?>
<strong<?php if (!empty($top_bar['custom_styles']['highlight_color'])): ?> style="color: <?php echo esc_attr($top_bar['custom_styles']['highlight_color']); ?>"<?php endif; ?>>
<?php echo esc_html($top_bar['highlight_text']); ?>
</strong>
<?php endif; ?>
<?php echo esc_html($top_bar['message_text']); ?>
</span>
<?php if ($top_bar['show_link'] && !empty($top_bar['link_text']) && !empty($top_bar['link_url'])): ?>
<a href="<?php echo esc_url(home_url($top_bar['link_url'])); ?>"
class="ms-2 text-white text-decoration-underline top-bar-link"
target="<?php echo esc_attr($top_bar['link_target']); ?>"
<?php if (!empty($top_bar['custom_styles']['link_hover_color'])): ?>
data-hover-color="<?php echo esc_attr($top_bar['custom_styles']['link_hover_color']); ?>"
<?php endif; ?>>
<?php echo esc_html($top_bar['link_text']); ?>
</a>
<?php endif; ?>
</div>
</div>
</div>
<?php endif; ?>
<!-- Los componentes dinámicos se cargarán aquí cuando se ejecute el algoritmo -->
<!-- Navbar (Template líneas 264-320) -->
<nav class="navbar navbar-expand-lg navbar-dark py-3" role="navigation" aria-label="<?php esc_attr_e('Primary Navigation', 'apus-theme'); ?>">

View File

@@ -1,302 +0,0 @@
<?php
/**
* Template Part: Navbar Configurable
*
* @package Apus_Theme
* @since 2.0.0
*/
// Obtener configuración usando Settings Manager
$settings_manager = new APUS_Settings_Manager();
$settings = $settings_manager->get_settings();
// Extraer configuración del componente
$navbar_config = isset($settings['components']['navbar'])
? $settings['components']['navbar']
: array();
// Los defaults ya están en Settings Manager, pero por seguridad validar
$defaults = array(
'enabled' => true,
'show_on_mobile' => true,
'show_on_desktop' => true,
'position' => 'sticky',
'responsive_breakpoint' => 'lg',
'enable_box_shadow' => true,
'enable_underline_effect' => true,
'enable_hover_background' => true,
'lets_talk_button' => array(
'enabled' => true,
'text' => "Let's Talk",
'icon_class' => 'bi bi-lightning-charge-fill',
'show_icon' => true,
'position' => 'right'
),
'dropdown' => array(
'enable_hover_desktop' => true,
'max_height' => 70,
'border_radius' => 8,
'item_padding_vertical' => 0.5,
'item_padding_horizontal' => 1.25
),
'custom_styles' => array(
'background_color' => '#1e3a5f',
'text_color' => '#ffffff',
'link_hover_color' => '#FF8600',
'link_hover_bg_color' => '#FF8600',
'dropdown_bg_color' => '#ffffff',
'dropdown_item_color' => '#4A5568',
'dropdown_item_hover_color' => '#FF8600',
'font_size' => 'normal',
'font_weight' => '500',
'box_shadow_intensity' => 'normal',
'border_radius' => 4,
'padding_vertical' => 0.75,
'link_padding_vertical' => 0.5,
'link_padding_horizontal' => 0.65,
'z_index' => 1030,
'transition_speed' => 'normal'
)
);
// Merge con defaults (por si acaso)
$config = wp_parse_args($navbar_config, $defaults);
// Verificar si está habilitado
if (!$config['enabled']) {
return;
}
// Construir clases CSS
$classes = array('navbar', 'navbar-expand-' . $config['responsive_breakpoint'], 'navbar-dark');
// Visibilidad responsive
if (!$config['show_on_mobile']) {
$classes[] = 'd-none';
$classes[] = 'd-' . $config['responsive_breakpoint'] . '-block';
}
if (!$config['show_on_desktop']) {
$classes[] = 'd-' . $config['responsive_breakpoint'] . '-none';
}
$class_attr = implode(' ', $classes);
// Construir estilos inline
$inline_styles = array();
// Background color
if (!empty($config['custom_styles']['background_color'])) {
$inline_styles[] = 'background-color: ' . esc_attr($config['custom_styles']['background_color']) . ' !important';
}
// Posición
$position_map = array(
'sticky' => 'sticky',
'static' => 'static',
'fixed' => 'fixed'
);
if (isset($position_map[$config['position']])) {
$inline_styles[] = 'position: ' . $position_map[$config['position']];
if ($config['position'] !== 'static') {
$inline_styles[] = 'top: 0';
}
}
// Z-index
$inline_styles[] = 'z-index: ' . absint($config['custom_styles']['z_index']);
// Padding
$inline_styles[] = 'padding: ' . floatval($config['custom_styles']['padding_vertical']) . 'rem 0';
// Box shadow
if ($config['enable_box_shadow']) {
$shadow_map = array(
'none' => 'none',
'light' => '0 2px 6px rgba(30, 58, 95, 0.08)',
'normal' => '0 4px 12px rgba(30, 58, 95, 0.15)',
'strong' => '0 6px 20px rgba(30, 58, 95, 0.25)'
);
if (isset($shadow_map[$config['custom_styles']['box_shadow_intensity']])) {
$inline_styles[] = 'box-shadow: ' . $shadow_map[$config['custom_styles']['box_shadow_intensity']];
}
}
// Transition
$transition_map = array(
'fast' => '0.2s',
'normal' => '0.3s',
'slow' => '0.5s'
);
if (isset($transition_map[$config['custom_styles']['transition_speed']])) {
$inline_styles[] = 'transition: all ' . $transition_map[$config['custom_styles']['transition_speed']] . ' ease';
}
$style_attr = !empty($inline_styles) ? ' style="' . implode('; ', $inline_styles) . '"' : '';
?>
<?php if (!empty($config['custom_styles'])): ?>
<style>
/* Navbar custom styles */
.navbar {
<?php if (!empty($config['custom_styles']['text_color'])): ?>
--navbar-link-color: <?php echo esc_attr($config['custom_styles']['text_color']); ?>;
<?php endif; ?>
<?php if (!empty($config['custom_styles']['link_hover_color'])): ?>
--navbar-link-hover-color: <?php echo esc_attr($config['custom_styles']['link_hover_color']); ?>;
<?php endif; ?>
<?php if (!empty($config['custom_styles']['link_hover_bg_color'])): ?>
--navbar-link-hover-bg: <?php echo esc_attr($config['custom_styles']['link_hover_bg_color']); ?>1a;
<?php endif; ?>
}
.navbar .nav-link {
color: var(--navbar-link-color, rgba(255, 255, 255, 0.9)) !important;
padding: <?php echo floatval($config['custom_styles']['link_padding_vertical']); ?>rem
<?php echo floatval($config['custom_styles']['link_padding_horizontal']); ?>rem !important;
font-size: <?php
$font_sizes = array('small' => '0.8rem', 'normal' => '0.9rem', 'large' => '1rem');
echo isset($font_sizes[$config['custom_styles']['font_size']])
? $font_sizes[$config['custom_styles']['font_size']]
: '0.9rem';
?>;
font-weight: <?php echo esc_attr($config['custom_styles']['font_weight']); ?>;
border-radius: <?php echo absint($config['custom_styles']['border_radius']); ?>px;
}
<?php if ($config['enable_hover_background']): ?>
.navbar .nav-link:hover {
color: var(--navbar-link-hover-color, #FF8600) !important;
background-color: var(--navbar-link-hover-bg, rgba(255, 133, 0, 0.1));
}
<?php endif; ?>
<?php if ($config['enable_underline_effect']): ?>
.navbar .nav-link::after {
background: var(--navbar-link-hover-color, #FF8600);
}
.navbar .nav-link:hover::after {
transform: translateX(-50%) scaleX(1);
}
<?php else: ?>
.navbar .nav-link::after {
display: none;
}
<?php endif; ?>
/* Dropdown styles */
.navbar .dropdown-menu {
<?php if (!empty($config['custom_styles']['dropdown_bg_color'])): ?>
background-color: <?php echo esc_attr($config['custom_styles']['dropdown_bg_color']); ?>;
<?php endif; ?>
max-height: <?php echo absint($config['dropdown']['max_height']); ?>vh;
border-radius: <?php echo absint($config['dropdown']['border_radius']); ?>px;
}
.navbar .dropdown-item {
<?php if (!empty($config['custom_styles']['dropdown_item_color'])): ?>
color: <?php echo esc_attr($config['custom_styles']['dropdown_item_color']); ?>;
<?php endif; ?>
padding: <?php echo floatval($config['dropdown']['item_padding_vertical']); ?>rem
<?php echo floatval($config['dropdown']['item_padding_horizontal']); ?>rem;
}
.navbar .dropdown-item:hover {
<?php if (!empty($config['custom_styles']['dropdown_item_hover_color'])): ?>
color: <?php echo esc_attr($config['custom_styles']['dropdown_item_hover_color']); ?>;
<?php endif; ?>
}
<?php if (!$config['dropdown']['enable_hover_desktop']): ?>
@media (min-width: 992px) {
.navbar .nav-item:hover > .dropdown-menu {
display: none !important;
}
}
<?php endif; ?>
</style>
<?php endif; ?>
<!-- Navbar Configurable -->
<nav class="<?php echo esc_attr($class_attr); ?>"<?php echo $style_attr; ?>
role="navigation"
aria-label="<?php esc_attr_e('Primary Navigation', 'apus-theme'); ?>">
<div class="container">
<!-- Hamburger Toggle Button -->
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="<?php esc_attr_e('Toggle navigation', 'apus-theme'); ?>">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Collapsible Menu -->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<?php
if (has_nav_menu('primary')) {
wp_nav_menu(array(
'theme_location' => 'primary',
'container' => false,
'menu_class' => 'navbar-nav mb-2 mb-lg-0',
'fallback_cb' => false,
'depth' => 2,
'walker' => new WP_Bootstrap_Navwalker(),
));
} else {
// Fallback si no hay menú asignado
?>
<ul class="navbar-nav mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="<?php echo esc_url(home_url('/')); ?>">
<?php esc_html_e('Home', 'apus-theme'); ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="<?php echo esc_url(get_post_type_archive_link('post')); ?>">
<?php esc_html_e('Blog', 'apus-theme'); ?>
</a>
</li>
</ul>
<?php
}
?>
<!-- Let's Talk Button -->
<?php if ($config['lets_talk_button']['enabled']): ?>
<?php
$button_position_class = '';
switch ($config['lets_talk_button']['position']) {
case 'left':
$button_position_class = 'me-auto';
break;
case 'center':
$button_position_class = 'mx-auto';
break;
case 'right':
default:
$button_position_class = 'ms-lg-3';
break;
}
?>
<button class="btn btn-lets-talk <?php echo esc_attr($button_position_class); ?>"
type="button"
data-bs-toggle="modal"
data-bs-target="#contactModal">
<?php if ($config['lets_talk_button']['show_icon'] && !empty($config['lets_talk_button']['icon_class'])): ?>
<i class="<?php echo esc_attr($config['lets_talk_button']['icon_class']); ?> me-2"></i>
<?php endif; ?>
<?php echo esc_html($config['lets_talk_button']['text']); ?>
</button>
<?php endif; ?>
</div>
</div><!-- .container -->
</nav><!-- .navbar -->