libreria-astro-lefebvre 0.2.30 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libreria-astro-lefebvre",
3
- "version": "0.2.30",
3
+ "version": "0.2.32",
4
4
  "description": "Librería de componentes Astro, React y Vue para Lefebvre",
5
5
  "author": "Equipo web desarrollo Lefebvre",
6
6
  "type": "module",
@@ -4,7 +4,7 @@ export const metadata: ComponentMetadata = {
4
4
  component_name: 'Cabecera_2027_Guadalajara',
5
5
  category: 'Header',
6
6
  name: 'Cabecera sticky con menú configurable 2027',
7
- description: 'Cabecera fija (sticky top-0) con logo de Lefebvre, botón CTA y menú horizontal completamente configurable vía prop "categories". Cada ítem admite target (_self o _blank). Los ítems personalizados no admiten subcategorías desde Mecano; solo el menú por defecto (si no se pasa menú custom) incluye el desplegable de Blog al hacer hover. Incluye hamburguesa en móvil y structured data schema.org (SiteNavigationElement raíz con la jerarquía del menú)',
7
+ description: 'Cabecera fija (sticky top-0) en dos filas en escritorio: logo de Lefebvre (enlaza a lefebvre.es) arriba y, debajo, menú horizontal completamente configurable vía prop "categories" y botón CTA a la derecha. En móvil, una sola fila con el logo, el botón y la hamburguesa. Cada ítem admite target (_self o _blank). Los ítems personalizados no admiten subcategorías desde Mecano; solo el menú por defecto (si no se pasa menú custom) incluye el desplegable de Blog al hacer hover. Incluye hamburguesa en móvil y structured data schema.org (SiteNavigationElement raíz con la jerarquía del menú)',
8
8
  framework: 'Astro',
9
9
  priority: 1,
10
10
  tags: ['header', 'cabecera', 'navegacion', 'sticky', 'menu', 'cta', 'configurable'],
@@ -54,6 +54,7 @@ export const metadata: ComponentMetadata = {
54
54
  { name: 'name', type: 'text', help: 'Texto visible del ítem del menú principal', label: 'Texto del ítem', example_value: 'Cómo funciona' },
55
55
  { name: 'link', type: 'text', help: 'URL de destino del ítem. Debe ser la ruta completa (no se le concatena "subdirectory")', label: 'URL del ítem', example_value: '/genia-l/conoce-genia-l/' },
56
56
  { name: 'target', type: 'select', help: 'Cómo se abre el enlace: "_self" en la misma pestaña, "_blank" en una pestaña nueva', label: 'Apertura del enlace', options: ['_self', '_blank'], options_labels: ['Misma pestaña', 'Nueva pestaña'], example_value: '_self' },
57
+ { name: 'featured', type: 'boolean', help: 'Muestra este ítem como el nombre del sitio (tipografía serif en negrita), junto al logo. En móvil sale de la hamburguesa. Actívalo solo en un ítem', label: 'Mostrar como marca del sitio', options: ['false', 'true'], options_labels: ['Falso', 'Verdadero'], example_value: false },
57
58
  ]
58
59
  }
59
60
  },
@@ -9,6 +9,7 @@ interface MenuItem {
9
9
  name: string;
10
10
  link: string;
11
11
  target?: string;
12
+ featured?: boolean | string;
12
13
  subcategories: SubMenuItem[];
13
14
  }
14
15
 
@@ -88,20 +89,32 @@ const categories: MenuItem[] = (categoriesProp && categoriesProp.length > 0)
88
89
 
89
90
  const structuredData = `<script type="application/ld+json">${structuredDataJson}</script>`;
90
91
 
92
+ // El CTA se pinta dos veces (barra superior en móvil, fila del menú en escritorio); solo uno es visible a la vez.
93
+ // Ítem marcado como "featured" (p. ej. GenIA-L): estilo "Lead/Bold". En móvil sale de la hamburguesa y va en la barra superior.
94
+ // El menú por defecto no tiene ninguno; cada página decide cuál destacar.
95
+ const firstItem = categories.find((c: any) => String(c.featured) === 'true');
96
+ const firstItemClass = 'font-heading text-xl not-italic font-semibold leading-7 tracking-[-0.05px] text-[#1b1b1b] whitespace-nowrap';
97
+ const ctaClass = 'h-12 max-[375px] px-3 md:px-5 py-3 font-body font-semibold max-[375px]:text-sm max-[375px]:leading-[21px] text-base leading-6 border-1 border-[#d71635] bg-[#d71635] text-[#ffffff] hover:border-[#71131f] hover:bg-[#71131f] transition-all duration-300 rounded-full cursor-pointer shadow-[0_2px_4px_-2px_rgba(107,58,8,0.08),0_4px_8px_-2px_rgba(107,58,8,0.04)] whitespace-nowrap';
98
+
91
99
 
92
100
  ---
93
101
 
94
102
  <header class="sticky top-0 w-full font-body bg-[rgba(250,250,245,0.80)] backdrop-blur-lg z-50 flex flex-col justify-center align-center items-center p-0">
95
- <nav class="px-4 py-3 w-full">
96
-
97
- <div class="max-w-7xl flex items-center justify-between mx-auto">
98
- <a href={subdirectory + '/'} class="flex items-center">
99
- <img src="https://assets.lefebvre.es/media/logos-2/svg/lefebvre.svg" class="h-10" alt="GenIA-L Lefebvre" width="160" height="40" loading={loading}>
100
- </a>
101
- <div class="flex items-center gap-4">
103
+ <div class="px-4 md:px-8 py-3 md:py-1 w-full">
104
+
105
+ <div class="max-w-[1376px] flex items-center justify-between gap-2 mx-auto">
106
+ <div class="flex items-center gap-3 min-w-0">
107
+ <a href="https://lefebvre.es" class="flex items-center shrink-0">
108
+ <img src="https://assets.lefebvre.es/media/logos-2/svg/lefebvre.svg" class="h-7 w-auto" alt="Lefebvre" width="104" height="28" loading={loading}>
109
+ </a>
110
+ {firstItem && (
111
+ <a href={firstItem.link} target={firstItem.target ?? '_self'} class={`${firstItemClass} min-w-0 truncate md:hidden`}>{firstItem.name}</a>
112
+ )}
113
+ </div>
114
+ <div class="flex items-center gap-2 shrink-0 lg:hidden">
102
115
  {label && (
103
116
  <div class="flex items-center gap-4">
104
- <a href={url} class="h-12 max-[375px] px-3 md:px-5 py-3 font-body font-semibold max-[375px]:text-sm max-[375px]:leading-[21px] text-base leading-6 border-1 border-[#d71635] bg-[#d71635] text-[#ffffff] hover:border-[#71131f] hover:bg-[#71131f] transition-all duration-300 rounded-full cursor-pointer shadow-[0_2px_4px_-2px_rgba(107,58,8,0.08),0_4px_8px_-2px_rgba(107,58,8,0.04)]">{label}</a>
117
+ <a href={url} class={ctaClass}>{label}</a>
105
118
  </div>
106
119
  )}
107
120
  <button onclick="document.getElementById('navbar-default').classList.toggle('hidden'); event.target.classList.toggle('bg-[#fafaf5]');"
@@ -117,17 +130,18 @@ const categories: MenuItem[] = (categoriesProp && categoriesProp.length > 0)
117
130
  </div>
118
131
 
119
132
  </div>
120
- </nav>
121
- <nav class="w-full flex items-center">
122
- <ul class="max-w-7xl hidden md:flex items-center justify-start md:gap-2 lg:gap-8 mx-auto">
133
+ </div>
134
+ <nav class="hidden md:block w-full px-8">
135
+ <div class="max-w-[1376px] flex items-center gap-6 mx-auto">
136
+ <ul class="flex items-center justify-start">
123
137
  {categories.map((category, index) => {
124
138
  const isActive = currentPath.includes(category.link) ||
125
139
  (subdirectory !== '' && (subdirectory + currentPath).includes(category.link));
126
140
  const hasSub = category.subcategories?.length > 0;
127
141
  const submenuId = `${identifier}-d-${index}`;
128
142
  return (
129
- <li class={`relative flex items-center border-b-4 hover:border-b-4 hover:border-[#d71635] hover:bg-[#ebe7da] ${isActive ? 'border-b-4 border-[#d71635] active' : 'border-transparent'}`}>
130
- <a href={category.link} target={category.target ?? '_self'} class={`flex items-center py-6 md:pl-4 lg:pl-8 ${hasSub ? '' : 'md:pr-4 lg:pr-8'}`}>
143
+ <li class={`relative flex items-center h-[72px] border-b-4 hover:border-b-4 hover:border-[#d71635] hover:bg-[#ebe7da] ${isActive ? 'border-b-4 border-[#d71635] active' : 'border-transparent'}`}>
144
+ <a href={category.link} target={category.target ?? '_self'} class={`flex items-center h-full pl-4 ${hasSub ? '' : 'pr-4'} ${category === firstItem ? firstItemClass : ''}`}>
131
145
  <span>
132
146
  {category.name}
133
147
  </span>
@@ -135,7 +149,7 @@ const categories: MenuItem[] = (categoriesProp && categoriesProp.length > 0)
135
149
  {hasSub && (
136
150
  <button
137
151
  type="button"
138
- class={`${identifier}-toggle flex items-center py-6 pl-2 md:pr-4 lg:pr-8 cursor-pointer`}
152
+ class={`${identifier}-toggle flex items-center h-full pl-2 pr-4 cursor-pointer`}
139
153
  aria-label={`Mostrar submenú de ${category.name}`}
140
154
  aria-expanded="false"
141
155
  aria-controls={submenuId}
@@ -161,6 +175,12 @@ const categories: MenuItem[] = (categoriesProp && categoriesProp.length > 0)
161
175
  </li>
162
176
  )})}
163
177
  </ul>
178
+ {label && (
179
+ <div class="ml-auto hidden lg:flex items-center">
180
+ <a href={url} class={ctaClass}>{label}</a>
181
+ </div>
182
+ )}
183
+ </div>
164
184
  </nav>
165
185
 
166
186
  <nav class="hidden w-full bg-white border-[#e1c8b4]" id="navbar-default">
@@ -173,6 +193,7 @@ const categories: MenuItem[] = (categoriesProp && categoriesProp.length > 0)
173
193
  (subdirectory !== '' && (subdirectory + currentPath).includes(category.link));
174
194
  const hasSub = category.subcategories?.length > 0;
175
195
  const submenuId = `${identifier}-m-${index}`;
196
+ if (category === firstItem) return null;
176
197
  return (
177
198
  <li class={`relative flex items-center px-6 py-4 border-b-2 hover:border-b-2 hover:border-[#d71635] ${isActive ? 'border-b-4 border-[#d71635] active' : 'border-transparent'}`}>
178
199
  <a href={category.link} target={category.target ?? '_self'} class="flex items-center">