libreria-astro-lefebvre 0.1.26 → 0.1.27
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
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ComponentMetadata } from '../interfaces/types';
|
|
2
|
+
|
|
3
|
+
export const metadata: ComponentMetadata = {
|
|
4
|
+
component_name: 'Mapa_2026_Girona',
|
|
5
|
+
category: 'Contenido de Imagen',
|
|
6
|
+
name: 'Mapa de contacto Google 2026',
|
|
7
|
+
description: 'Sección de contacto con un mapa de Google Maps embebido (no requiere API key) junto a un panel con los datos de contacto: dirección, teléfono, email y horario. El mapa se construye automáticamente a partir de la dirección, o se puede pegar directamente el enlace de "Insertar un mapa" de Google. Incluye botón "Cómo llegar" y structured data schema.org (LocalBusiness + PostalAddress)',
|
|
8
|
+
framework: 'Astro',
|
|
9
|
+
priority: 1,
|
|
10
|
+
tags: ['mapa', 'google maps', 'contacto', 'ubicacion', 'direccion'],
|
|
11
|
+
fields: [
|
|
12
|
+
{
|
|
13
|
+
name: 'title',
|
|
14
|
+
type: 'text',
|
|
15
|
+
help: 'Título de la sección (opcional). Se muestra centrado sobre el mapa',
|
|
16
|
+
label: 'Título',
|
|
17
|
+
mandatory: false,
|
|
18
|
+
example_value: 'Dónde encontrarnos'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'description',
|
|
22
|
+
type: 'textArea',
|
|
23
|
+
help: 'Texto introductorio opcional que se muestra bajo el título',
|
|
24
|
+
label: 'Descripción',
|
|
25
|
+
mandatory: false,
|
|
26
|
+
example_value: 'Ven a visitarnos o ponte en contacto con nosotros.'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'address',
|
|
30
|
+
type: 'text',
|
|
31
|
+
help: 'Dirección completa del lugar. Se usa para generar el mapa, el enlace "Cómo llegar" y el structured data. Ejemplo: "Carrer de la Força, 8, 17004 Girona"',
|
|
32
|
+
label: 'Dirección',
|
|
33
|
+
mandatory: true,
|
|
34
|
+
example_value: 'Carrer de la Força, 8, 17004 Girona'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'embedUrl',
|
|
38
|
+
type: 'textArea',
|
|
39
|
+
help: 'Opcional. Si quieres un mapa más preciso, pega aquí el enlace del campo "src" que aparece en Google Maps > Compartir > Insertar un mapa. Si lo rellenas, tiene prioridad sobre la dirección',
|
|
40
|
+
label: 'Enlace de inserción de Google Maps (opcional)',
|
|
41
|
+
mandatory: false,
|
|
42
|
+
example_value: ''
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'zoom',
|
|
46
|
+
type: 'select',
|
|
47
|
+
help: 'Nivel de zoom del mapa cuando se genera a partir de la dirección. Valores bajos alejan, valores altos acercan. Se ignora si se rellena el enlace de inserción',
|
|
48
|
+
label: 'Zoom del mapa',
|
|
49
|
+
options: ['10', '12', '14', '15', '16', '17', '18'],
|
|
50
|
+
options_labels: ['10 (ciudad)', '12', '14', '15 (barrio)', '16', '17', '18 (calle)'],
|
|
51
|
+
example_value: '15'
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'mapPosition',
|
|
55
|
+
type: 'select',
|
|
56
|
+
help: 'Posición del mapa respecto al panel de datos de contacto en escritorio',
|
|
57
|
+
label: 'Posición del mapa',
|
|
58
|
+
options: ['right', 'left'],
|
|
59
|
+
options_labels: ['Mapa a la derecha', 'Mapa a la izquierda'],
|
|
60
|
+
example_value: 'right'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'showContactInfo',
|
|
64
|
+
type: 'boolean',
|
|
65
|
+
help: 'Muestra el panel lateral con los datos de contacto. Si se desactiva, el mapa ocupa todo el ancho',
|
|
66
|
+
label: 'Mostrar datos de contacto',
|
|
67
|
+
example_value: true
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'phone',
|
|
71
|
+
type: 'text',
|
|
72
|
+
help: 'Teléfono de contacto. Se muestra como enlace clicable (tel:)',
|
|
73
|
+
label: 'Teléfono',
|
|
74
|
+
mandatory: false,
|
|
75
|
+
example_value: '+34 972 00 00 00'
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'email',
|
|
79
|
+
type: 'text',
|
|
80
|
+
help: 'Email de contacto. Se muestra como enlace clicable (mailto:)',
|
|
81
|
+
label: 'Email',
|
|
82
|
+
mandatory: false,
|
|
83
|
+
example_value: 'contacto@ejemplo.com'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'schedule',
|
|
87
|
+
type: 'textArea',
|
|
88
|
+
help: 'Horario de atención. Admite varias líneas',
|
|
89
|
+
label: 'Horario',
|
|
90
|
+
mandatory: false,
|
|
91
|
+
example_value: 'Lunes a Viernes: 9:00 - 18:00'
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
const {
|
|
3
|
+
title = '',
|
|
4
|
+
description = '',
|
|
5
|
+
address = '',
|
|
6
|
+
embedUrl = '',
|
|
7
|
+
zoom = '15',
|
|
8
|
+
mapPosition = 'right',
|
|
9
|
+
showContactInfo = true,
|
|
10
|
+
phone = '',
|
|
11
|
+
email = '',
|
|
12
|
+
schedule = '',
|
|
13
|
+
} = Astro.props;
|
|
14
|
+
|
|
15
|
+
// Si el usuario pega el src completo del iframe de "Insertar un mapa" de Google, se usa tal cual.
|
|
16
|
+
// Si no, se construye un embed a partir de la dirección (no requiere API key).
|
|
17
|
+
const mapSrc = embedUrl
|
|
18
|
+
? embedUrl
|
|
19
|
+
: address
|
|
20
|
+
? `https://maps.google.com/maps?q=${encodeURIComponent(address)}&z=${encodeURIComponent(zoom)}&output=embed`
|
|
21
|
+
: '';
|
|
22
|
+
|
|
23
|
+
// Enlace "Cómo llegar" que abre Google Maps con la dirección como destino.
|
|
24
|
+
const directionsUrl = address
|
|
25
|
+
? `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(address)}`
|
|
26
|
+
: '';
|
|
27
|
+
|
|
28
|
+
const hasInfo = showContactInfo && (address || phone || email || schedule);
|
|
29
|
+
|
|
30
|
+
const escapeJson = (s = '') => String(s).replace(/<[^>]*>/g, '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/[\n\r\t]+/g, ' ');
|
|
31
|
+
|
|
32
|
+
const structuredData = address ? `<script type="application/ld+json">
|
|
33
|
+
{
|
|
34
|
+
"@context": "https://schema.org",
|
|
35
|
+
"@type": "LocalBusiness"${title ? `,
|
|
36
|
+
"name": "${escapeJson(title)}"` : ''},
|
|
37
|
+
"address": {
|
|
38
|
+
"@type": "PostalAddress",
|
|
39
|
+
"streetAddress": "${escapeJson(address)}"
|
|
40
|
+
}${phone ? `,
|
|
41
|
+
"telephone": "${escapeJson(phone)}"` : ''}${email ? `,
|
|
42
|
+
"email": "${escapeJson(email)}"` : ''}
|
|
43
|
+
}
|
|
44
|
+
</script>` : '';
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
<section class="w-full max-w-[1200px] mx-auto px-6 md:px-0 py-10">
|
|
48
|
+
{(title || description) && (
|
|
49
|
+
<div class="mb-8 text-center">
|
|
50
|
+
{title && (
|
|
51
|
+
<h2 class="font-poppins text-[#262626] text-3xl md:text-4xl not-italic font-semibold leading-tight tracking-tight mb-4" set:html={title} />
|
|
52
|
+
)}
|
|
53
|
+
{description && (
|
|
54
|
+
<p class="text-[#363942] font-inter font-normal text-base md:text-lg not-italic max-w-2xl mx-auto" set:html={description} />
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
|
|
59
|
+
<div class={`w-full flex flex-col gap-6 ${hasInfo ? (mapPosition === 'left' ? 'lg:flex-row' : 'lg:flex-row-reverse') : ''} items-stretch`}>
|
|
60
|
+
<div class={`w-full ${hasInfo ? 'lg:w-2/3' : ''}`}>
|
|
61
|
+
{mapSrc ? (
|
|
62
|
+
<iframe
|
|
63
|
+
src={mapSrc}
|
|
64
|
+
title={title || 'Mapa de ubicación'}
|
|
65
|
+
width="100%"
|
|
66
|
+
height="450"
|
|
67
|
+
style="border:0;"
|
|
68
|
+
loading="lazy"
|
|
69
|
+
referrerpolicy="no-referrer-when-downgrade"
|
|
70
|
+
allowfullscreen
|
|
71
|
+
class="w-full h-[350px] md:h-[450px] rounded-2xl shadow-sm"
|
|
72
|
+
></iframe>
|
|
73
|
+
) : (
|
|
74
|
+
<div class="w-full h-[350px] md:h-[450px] rounded-2xl bg-[#F2F2F2] flex items-center justify-center text-[#363942] font-inter text-sm">
|
|
75
|
+
Añade una dirección o un enlace de Google Maps para mostrar el mapa
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
{hasInfo && (
|
|
81
|
+
<div class="w-full lg:w-1/3 flex flex-col justify-center gap-5 p-6 rounded-2xl bg-[#F8F8F8]">
|
|
82
|
+
{address && (
|
|
83
|
+
<div class="flex items-start gap-3">
|
|
84
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 mt-0.5 shrink-0">
|
|
85
|
+
<path d="M12 21s7-5.686 7-11a7 7 0 1 0-14 0c0 5.314 7 11 7 11Z" stroke="#262626" stroke-width="1.5" stroke-linejoin="round"></path>
|
|
86
|
+
<circle cx="12" cy="10" r="2.5" stroke="#262626" stroke-width="1.5"></circle>
|
|
87
|
+
</svg>
|
|
88
|
+
<p class="text-[#363942] font-inter text-base not-italic" set:html={address} />
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
{phone && (
|
|
92
|
+
<div class="flex items-center gap-3">
|
|
93
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 shrink-0">
|
|
94
|
+
<path d="M3 5.5C3 4.67 3.67 4 4.5 4h2.1c.46 0 .86.31.97.76l.86 3.42a1 1 0 0 1-.27.95l-1.5 1.5a14.5 14.5 0 0 0 5.25 5.25l1.5-1.5a1 1 0 0 1 .95-.27l3.42.86c.45.11.76.51.76.97v2.1c0 .83-.67 1.5-1.5 1.5A16.5 16.5 0 0 1 3 5.5Z" stroke="#262626" stroke-width="1.5" stroke-linejoin="round"></path>
|
|
95
|
+
</svg>
|
|
96
|
+
<a href={`tel:${String(phone).replace(/\s+/g, '')}`} class="text-[#363942] font-inter text-base not-italic hover:text-[#2134F1] transition-colors duration-300">{phone}</a>
|
|
97
|
+
</div>
|
|
98
|
+
)}
|
|
99
|
+
{email && (
|
|
100
|
+
<div class="flex items-center gap-3">
|
|
101
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 shrink-0">
|
|
102
|
+
<rect x="3" y="5" width="18" height="14" rx="2" stroke="#262626" stroke-width="1.5"></rect>
|
|
103
|
+
<path d="m4 7 8 5 8-5" stroke="#262626" stroke-width="1.5" stroke-linejoin="round"></path>
|
|
104
|
+
</svg>
|
|
105
|
+
<a href={`mailto:${email}`} class="text-[#363942] font-inter text-base not-italic hover:text-[#2134F1] transition-colors duration-300 break-all">{email}</a>
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
{schedule && (
|
|
109
|
+
<div class="flex items-start gap-3">
|
|
110
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 mt-0.5 shrink-0">
|
|
111
|
+
<circle cx="12" cy="12" r="9" stroke="#262626" stroke-width="1.5"></circle>
|
|
112
|
+
<path d="M12 7v5l3 2" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
113
|
+
</svg>
|
|
114
|
+
<div class="text-[#363942] font-inter text-base not-italic" set:html={schedule} />
|
|
115
|
+
</div>
|
|
116
|
+
)}
|
|
117
|
+
{directionsUrl && (
|
|
118
|
+
<a href={directionsUrl} target="_blank" rel="noopener noreferrer" class="inline-block w-fit h-11 md:h-12 text-[#2134F1] font-inter font-semibold bg-[#ffffff] px-5 py-3 border border-[#2134F1] rounded-lg shadow-md hover:bg-[#DDE0EC] transition-all duration-300 text-sm md:text-base">Cómo llegar</a>
|
|
119
|
+
)}
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
</section>
|
|
124
|
+
|
|
125
|
+
{structuredData && <Fragment set:html={structuredData} />}
|
|
@@ -52,6 +52,7 @@ import * as Imagen_2025_Bogota from '../carbins/Imagen_2025_Bogota.ts';
|
|
|
52
52
|
import * as Imagen_2025_Fukushima from '../carbins/Imagen_2025_Fukushima.ts';
|
|
53
53
|
import * as Imagen_2026_Algar from '../carbins/Imagen_2026_Algar.ts';
|
|
54
54
|
import * as Indice_2025_Taiwan from '../carbins/Indice_2025_Taiwan.ts';
|
|
55
|
+
import * as Mapa_2026_Girona from '../carbins/Mapa_2026_Girona.ts';
|
|
55
56
|
import * as Modal_2025_Sagunto from '../carbins/Modal_2025_Sagunto.ts';
|
|
56
57
|
import * as Paginacion_2025_Paris from '../carbins/Paginacion_2025_Paris.ts';
|
|
57
58
|
import * as RRSS_2025_Pisa from '../carbins/RRSS_2025_Pisa.ts';
|
|
@@ -139,6 +140,7 @@ export const components = [
|
|
|
139
140
|
{component: Imagen_2025_Fukushima},
|
|
140
141
|
{component: Imagen_2026_Algar},
|
|
141
142
|
{component: Indice_2025_Taiwan},
|
|
143
|
+
{component: Mapa_2026_Girona},
|
|
142
144
|
{component: Modal_2025_Sagunto},
|
|
143
145
|
{component: Paginacion_2025_Paris},
|
|
144
146
|
{component: RRSS_2025_Pisa},
|
package/src/index.ts
CHANGED
|
@@ -59,6 +59,7 @@ import Imagen_2025_Bogota from './components/Astro/Imagen_2025_Bogota.astro';
|
|
|
59
59
|
import Imagen_2025_Fukushima from './components/Astro/Imagen_2025_Fukushima.astro';
|
|
60
60
|
import Imagen_2026_Algar from './components/Astro/Imagen_2026_Algar.astro';
|
|
61
61
|
import Indice_2025_Taiwan from './components/Astro/Indice_2025_Taiwan.astro';
|
|
62
|
+
import Mapa_2026_Girona from './components/Astro/Mapa_2026_Girona.astro';
|
|
62
63
|
import Modal_2025_Sagunto from './components/Astro/Modal_2025_Sagunto.astro';
|
|
63
64
|
import Paginacion_2025_Paris from './components/Astro/Paginacion_2025_Paris.astro';
|
|
64
65
|
import RRSS_2025_Pisa from './components/Astro/RRSS_2025_Pisa.astro';
|
|
@@ -95,7 +96,7 @@ import ReactButton from './components/React/ReactButton.jsx';
|
|
|
95
96
|
// Exporta todos los componentes uno a uno para que puedan ser usados directamente.
|
|
96
97
|
|
|
97
98
|
|
|
98
|
-
export { VueButton, Author_2025_Algarve, Button, CTA_2025_Formentera, Cabecera_2025_Barcelona, Cabecera_2025_Madrid, Cabecera_2026_Bilbao, Cabecera_2026_Madrid, Card_2025_Malta, Contenido_2025_Alcorcon, Contenido_2025_Cordoba, Contenido_2025_Granada, Contenido_2025_Malaga, Contenido_2025_Montevideo, Contenido_2026_Cabra, Contenido_2026_Denia, Contenido_2026_Dubai, Contenido_2026_Estocolmo, Contenido_2026_Jaen, Contenido_2026_Leon, Contenido_2026_Mallorca, Contenido_2026_Marruecos, Contenido_2026_Menorca, Contenido_2026_Michigan, Contenido_2026_Moraira, Contenido_2026_Mostoles, Contenido_2026_Orcasitas, Contenido_2026_Oslo, Contenido_2026_Quito, Contenido_2026_Seattle, Contenido_2026_Sevilla, Contenido_2026_Tokyo, Contenido_2026_Ubeda, Contenido_2026_Yakarta, CorpFooter, CorpHero, CorpNavigation, Enlace_2025_Venecia, FAQ_2025_Hiroshima, Footer_2025_Napoles, Formulario_2025_Nara, Formulario_2025_Seul, Formulario_2025_Teruel, Formulario_2026_Carabanchel, Formulario_2026_Wichita, Galeria_2026_Segorbe, GeometricShape, GeometricShapeCard, HeaderCorporativo, Hero_2025_Benidorm, Hero_2026_Benidorm, ImageTextSimple, Imagen_2025_Bogota, Imagen_2025_Fukushima, Imagen_2026_Algar, Indice_2025_Taiwan, Modal_2025_Sagunto, Paginacion_2025_Paris, RRSS_2025_Pisa, SEO_Head_Section, SEO_Schema_Page, Separador_2025_Reinosa, Separador_2025_Toledo, Share_2025_Florencia, SpectrumSeparator, Sumario_2025_Beijing, Tabla_2025_Fuenlabrada, Tabla_2026_Cadiz, Tag_2025_Bolonia, TestHijo, TestPadre, Test_2026_Gaza, TextBox, TextImageBackground, TextImageBlock, TextImageCard, TextImageHeader, Texto_2025_Kyoto, Texto_2026_Alicante, Texto_2026_Castellon, Tiempo_2025_Londres, Titulo_2025_Algeciras, Titulo_2025_Santorini, VideoAutoplay, Video_2025_Polop, Video_2025_Valencia, Video_2026_Andujar, ReactButton };
|
|
99
|
+
export { VueButton, Author_2025_Algarve, Button, CTA_2025_Formentera, Cabecera_2025_Barcelona, Cabecera_2025_Madrid, Cabecera_2026_Bilbao, Cabecera_2026_Madrid, Card_2025_Malta, Contenido_2025_Alcorcon, Contenido_2025_Cordoba, Contenido_2025_Granada, Contenido_2025_Malaga, Contenido_2025_Montevideo, Contenido_2026_Cabra, Contenido_2026_Denia, Contenido_2026_Dubai, Contenido_2026_Estocolmo, Contenido_2026_Jaen, Contenido_2026_Leon, Contenido_2026_Mallorca, Contenido_2026_Marruecos, Contenido_2026_Menorca, Contenido_2026_Michigan, Contenido_2026_Moraira, Contenido_2026_Mostoles, Contenido_2026_Orcasitas, Contenido_2026_Oslo, Contenido_2026_Quito, Contenido_2026_Seattle, Contenido_2026_Sevilla, Contenido_2026_Tokyo, Contenido_2026_Ubeda, Contenido_2026_Yakarta, CorpFooter, CorpHero, CorpNavigation, Enlace_2025_Venecia, FAQ_2025_Hiroshima, Footer_2025_Napoles, Formulario_2025_Nara, Formulario_2025_Seul, Formulario_2025_Teruel, Formulario_2026_Carabanchel, Formulario_2026_Wichita, Galeria_2026_Segorbe, GeometricShape, GeometricShapeCard, HeaderCorporativo, Hero_2025_Benidorm, Hero_2026_Benidorm, ImageTextSimple, Imagen_2025_Bogota, Imagen_2025_Fukushima, Imagen_2026_Algar, Indice_2025_Taiwan, Mapa_2026_Girona, Modal_2025_Sagunto, Paginacion_2025_Paris, RRSS_2025_Pisa, SEO_Head_Section, SEO_Schema_Page, Separador_2025_Reinosa, Separador_2025_Toledo, Share_2025_Florencia, SpectrumSeparator, Sumario_2025_Beijing, Tabla_2025_Fuenlabrada, Tabla_2026_Cadiz, Tag_2025_Bolonia, TestHijo, TestPadre, Test_2026_Gaza, TextBox, TextImageBackground, TextImageBlock, TextImageCard, TextImageHeader, Texto_2025_Kyoto, Texto_2026_Alicante, Texto_2026_Castellon, Tiempo_2025_Londres, Titulo_2025_Algeciras, Titulo_2025_Santorini, VideoAutoplay, Video_2025_Polop, Video_2025_Valencia, Video_2026_Andujar, ReactButton };
|
|
99
100
|
|
|
100
101
|
|
|
101
102
|
// Exporta la función listComponents para que sea usado en el Pagebuilder en Vue.
|
|
@@ -166,6 +167,7 @@ export const components = {
|
|
|
166
167
|
Imagen_2025_Fukushima: Imagen_2025_Fukushima,
|
|
167
168
|
Imagen_2026_Algar: Imagen_2026_Algar,
|
|
168
169
|
Indice_2025_Taiwan: Indice_2025_Taiwan,
|
|
170
|
+
Mapa_2026_Girona: Mapa_2026_Girona,
|
|
169
171
|
Modal_2025_Sagunto: Modal_2025_Sagunto,
|
|
170
172
|
Paginacion_2025_Paris: Paginacion_2025_Paris,
|
|
171
173
|
RRSS_2025_Pisa: RRSS_2025_Pisa,
|