@synthex-engineers/refined-tech 1.0.1 → 1.0.3
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/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.js.map +1 -1
- package/dist/astro/components/ClientTrustCard.astro +79 -79
- package/dist/astro/components/FooterBounceCurve.astro +302 -0
- package/dist/astro/components/HelpTooltip.astro +191 -71
- package/dist/astro/components/Preloader.astro +240 -0
- package/dist/astro/components/WavyUnderlineHeading.astro +13 -5
- package/dist/astro/index.d.ts +2 -0
- package/dist/astro/index.js +2 -0
- package/dist/index.cjs +27 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +27 -15
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/registry/components.json +24 -12
- package/package.json +1 -1
|
@@ -16,104 +16,224 @@ const {
|
|
|
16
16
|
align = 'center',
|
|
17
17
|
className = '',
|
|
18
18
|
} = Astro.props;
|
|
19
|
-
|
|
20
|
-
const alignClasses = {
|
|
21
|
-
left: 'left-0 translate-x-0',
|
|
22
|
-
center: 'left-1/2 -translate-x-1/2',
|
|
23
|
-
right: 'right-0 translate-x-0',
|
|
24
|
-
}[align];
|
|
25
|
-
|
|
26
|
-
const arrowAlignClasses = {
|
|
27
|
-
left: 'left-3',
|
|
28
|
-
center: 'left-1/2 -translate-x-1/2',
|
|
29
|
-
right: 'right-3',
|
|
30
|
-
}[align];
|
|
31
19
|
---
|
|
32
20
|
|
|
33
|
-
<span
|
|
21
|
+
<span
|
|
22
|
+
class={`relative inline-flex items-center group/bubble ml-1.5 align-middle ${className}`}
|
|
23
|
+
data-align={align}
|
|
24
|
+
>
|
|
34
25
|
<button
|
|
35
26
|
type="button"
|
|
36
|
-
class="info-bubble-trigger w-4 h-4 rounded-full bg-white/10 hover:bg-
|
|
27
|
+
class="info-bubble-trigger w-4 h-4 rounded-full bg-white/10 hover:bg-pistachio/20 text-white/70 hover:text-pistachio border border-white/20 hover:border-pistachio/40 text-xs font-mono font-bold inline-flex items-center justify-center cursor-help transition-all duration-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-pistachio shrink-0 select-none"
|
|
37
28
|
aria-label={`${title}: ${description}`}
|
|
29
|
+
aria-expanded="false"
|
|
38
30
|
>
|
|
39
31
|
?
|
|
40
32
|
</button>
|
|
41
33
|
|
|
42
|
-
<!-- Popover Flotante Accesible (Hover &
|
|
34
|
+
<!-- Popover Flotante Accesible (Hover, Focus & Click/Tap): sale justo arriba a 8px sin tapar el botón ? -->
|
|
43
35
|
<span
|
|
44
36
|
role="tooltip"
|
|
45
|
-
class=
|
|
37
|
+
class="info-bubble-tooltip absolute bottom-[calc(100%+8px)] left-1/2 -translate-x-1/2 w-64 sm:w-72 max-w-[calc(100vw-32px)] p-3.5 rounded-xl border border-white/20 text-left shadow-2xl z-[100] pointer-events-none opacity-0 invisible transition-opacity duration-200"
|
|
46
38
|
>
|
|
47
|
-
<span class="block text-xs font-display font-bold text-
|
|
39
|
+
<span class="block text-xs font-display font-bold text-pistachio mb-1" data-i18n={titleKey}>
|
|
48
40
|
{title}
|
|
49
41
|
</span>
|
|
50
42
|
<span class="block text-xs font-body text-white/90 leading-relaxed" data-i18n={descKey}>
|
|
51
43
|
{description}
|
|
52
44
|
</span>
|
|
53
45
|
|
|
54
|
-
<!-- Flecha indicadora
|
|
46
|
+
<!-- Flecha indicadora apuntando al botón ? -->
|
|
55
47
|
<span
|
|
56
|
-
class=
|
|
48
|
+
class="info-bubble-arrow absolute top-full left-1/2 -translate-x-1/2 -mt-[1px] border-[5px] border-transparent border-t-[#141414] pointer-events-none"
|
|
57
49
|
></span>
|
|
58
50
|
</span>
|
|
59
51
|
</span>
|
|
60
52
|
|
|
53
|
+
<style is:global>
|
|
54
|
+
/* Visibilidad y z-index garantizados independientemente de Tailwind */
|
|
55
|
+
.group\/bubble:hover .info-bubble-tooltip,
|
|
56
|
+
.group\/bubble:focus-within .info-bubble-tooltip,
|
|
57
|
+
.group\/bubble[data-state="open"] .info-bubble-tooltip,
|
|
58
|
+
.group\/bubble.is-open .info-bubble-tooltip {
|
|
59
|
+
opacity: 1 !important;
|
|
60
|
+
pointer-events: auto !important;
|
|
61
|
+
visibility: visible !important;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.group\/bubble:hover,
|
|
65
|
+
.group\/bubble:focus-within,
|
|
66
|
+
.group\/bubble[data-state="open"],
|
|
67
|
+
.group\/bubble.is-open {
|
|
68
|
+
z-index: 60 !important;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.info-bubble-tooltip {
|
|
72
|
+
background-color: #141414 !important;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Inversión vertical automática si no cabe por arriba */
|
|
76
|
+
.info-bubble-tooltip.is-inverted {
|
|
77
|
+
bottom: auto !important;
|
|
78
|
+
top: calc(100% + 8px) !important;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.info-bubble-arrow {
|
|
82
|
+
border-top-color: #141414 !important;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.info-bubble-tooltip.is-inverted .info-bubble-arrow {
|
|
86
|
+
top: auto !important;
|
|
87
|
+
bottom: 100% !important;
|
|
88
|
+
margin-top: 0 !important;
|
|
89
|
+
margin-bottom: -1px !important;
|
|
90
|
+
border-top-color: transparent !important;
|
|
91
|
+
border-bottom-color: #141414 !important;
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
94
|
+
|
|
61
95
|
<script>
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// Inversión vertical si no cabe por arriba
|
|
93
|
-
const arrow = tooltip.querySelector<HTMLElement>('.info-bubble-arrow');
|
|
94
|
-
if (rect.top < 60) {
|
|
95
|
-
tooltip.classList.remove('bottom-full', 'mb-2.5');
|
|
96
|
-
tooltip.classList.add('top-full', 'mt-2.5');
|
|
97
|
-
if (arrow) {
|
|
98
|
-
arrow.classList.remove('top-full', '-mt-[1px]', 'border-t-charcoal');
|
|
99
|
-
arrow.classList.add('bottom-full', '-mb-[1px]', 'border-b-charcoal');
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
tooltip.classList.remove('top-full', 'mt-2.5');
|
|
103
|
-
tooltip.classList.add('bottom-full', 'mb-2.5');
|
|
104
|
-
if (arrow) {
|
|
105
|
-
arrow.classList.remove('bottom-full', '-mb-[1px]', 'border-b-charcoal');
|
|
106
|
-
arrow.classList.add('top-full', '-mt-[1px]', 'border-t-charcoal');
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
});
|
|
96
|
+
function setupHelpTooltipSystem() {
|
|
97
|
+
if ((window as any).__synthexHelpTooltipInitialized) return;
|
|
98
|
+
(window as any).__synthexHelpTooltipInitialized = true;
|
|
99
|
+
|
|
100
|
+
let activeBubble: HTMLElement | null = null;
|
|
101
|
+
|
|
102
|
+
function closeActiveBubble() {
|
|
103
|
+
if (activeBubble) {
|
|
104
|
+
activeBubble.removeAttribute('data-state');
|
|
105
|
+
activeBubble.classList.remove('is-open');
|
|
106
|
+
const trigger = activeBubble.querySelector<HTMLButtonElement>('.info-bubble-trigger');
|
|
107
|
+
if (trigger) trigger.setAttribute('aria-expanded', 'false');
|
|
108
|
+
activeBubble = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function reposition(bubble: HTMLElement) {
|
|
113
|
+
const trigger = bubble.querySelector<HTMLElement>('.info-bubble-trigger');
|
|
114
|
+
const tooltip = bubble.querySelector<HTMLElement>('.info-bubble-tooltip');
|
|
115
|
+
const arrow = bubble.querySelector<HTMLElement>('.info-bubble-arrow');
|
|
116
|
+
if (!trigger || !tooltip) return;
|
|
117
|
+
|
|
118
|
+
// 1. Reset base
|
|
119
|
+
tooltip.classList.remove('is-inverted');
|
|
120
|
+
tooltip.style.left = '50%';
|
|
121
|
+
tooltip.style.transform = 'translateX(-50%)';
|
|
122
|
+
if (arrow) {
|
|
123
|
+
arrow.style.left = '50%';
|
|
124
|
+
arrow.style.transform = 'translateX(-50%)';
|
|
110
125
|
}
|
|
111
126
|
|
|
112
|
-
|
|
113
|
-
trigger.
|
|
127
|
+
// 2. Medir cotas en el viewport
|
|
128
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
129
|
+
const tooltipRect = tooltip.getBoundingClientRect();
|
|
130
|
+
const viewportWidth = window.innerWidth;
|
|
131
|
+
const margin = 16;
|
|
132
|
+
|
|
133
|
+
// 3. Comprobar si cabe verticalmente arriba (mínimo 60px libres desde el top)
|
|
134
|
+
if (triggerRect.top - tooltipRect.height - 12 < 60) {
|
|
135
|
+
tooltip.classList.add('is-inverted');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 4. Cálculo horizontal para no salirse de los límites de la pantalla
|
|
139
|
+
const triggerCenterX = triggerRect.left + (triggerRect.width / 2);
|
|
140
|
+
const idealLeft = triggerCenterX - (tooltipRect.width / 2);
|
|
141
|
+
const idealRight = idealLeft + tooltipRect.width;
|
|
142
|
+
|
|
143
|
+
let shiftX = 0;
|
|
144
|
+
if (idealRight > viewportWidth - margin) {
|
|
145
|
+
shiftX = (viewportWidth - margin) - idealRight;
|
|
146
|
+
} else if (idealLeft < margin) {
|
|
147
|
+
shiftX = margin - idealLeft;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (shiftX !== 0) {
|
|
151
|
+
tooltip.style.transform = `translateX(calc(-50% + ${shiftX}px))`;
|
|
152
|
+
|
|
153
|
+
// Mantener la flecha apuntando exactamente al centro del botón ?
|
|
154
|
+
if (arrow) {
|
|
155
|
+
const arrowLeft = (tooltipRect.width / 2) - shiftX;
|
|
156
|
+
const clampedArrowLeft = Math.max(14, Math.min(tooltipRect.width - 14, arrowLeft));
|
|
157
|
+
arrow.style.left = `${clampedArrowLeft}px`;
|
|
158
|
+
arrow.style.transform = 'translateX(-50%)';
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Delegación universal de Clic / Tap
|
|
164
|
+
document.addEventListener('click', (e) => {
|
|
165
|
+
const target = e.target as HTMLElement | null;
|
|
166
|
+
const trigger = target?.closest<HTMLButtonElement>('.info-bubble-trigger');
|
|
167
|
+
|
|
168
|
+
if (trigger) {
|
|
169
|
+
e.preventDefault();
|
|
170
|
+
e.stopPropagation();
|
|
171
|
+
const bubble = trigger.closest<HTMLElement>('.group\\/bubble');
|
|
172
|
+
if (!bubble) return;
|
|
173
|
+
|
|
174
|
+
const isOpen = bubble.getAttribute('data-state') === 'open' || bubble.classList.contains('is-open');
|
|
175
|
+
closeActiveBubble();
|
|
176
|
+
|
|
177
|
+
if (!isOpen) {
|
|
178
|
+
bubble.setAttribute('data-state', 'open');
|
|
179
|
+
bubble.classList.add('is-open');
|
|
180
|
+
trigger.setAttribute('aria-expanded', 'true');
|
|
181
|
+
activeBubble = bubble;
|
|
182
|
+
reposition(bubble);
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Si se hace clic dentro del tooltip, mantenerlo abierto
|
|
188
|
+
if (target?.closest('.info-bubble-tooltip')) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Clic fuera -> cerrar
|
|
193
|
+
closeActiveBubble();
|
|
114
194
|
});
|
|
195
|
+
|
|
196
|
+
// Delegación universal de Hover (MouseEnter & MouseOver en fase de captura)
|
|
197
|
+
document.addEventListener('mouseover', (e) => {
|
|
198
|
+
const target = e.target as HTMLElement | null;
|
|
199
|
+
const trigger = target?.closest<HTMLButtonElement>('.info-bubble-trigger');
|
|
200
|
+
if (trigger) {
|
|
201
|
+
const bubble = trigger.closest<HTMLElement>('.group\\/bubble');
|
|
202
|
+
if (bubble) reposition(bubble);
|
|
203
|
+
}
|
|
204
|
+
}, true);
|
|
205
|
+
|
|
206
|
+
// Delegación universal de Foco Accesible
|
|
207
|
+
document.addEventListener('focusin', (e) => {
|
|
208
|
+
const target = e.target as HTMLElement | null;
|
|
209
|
+
const trigger = target?.closest<HTMLButtonElement>('.info-bubble-trigger');
|
|
210
|
+
if (trigger) {
|
|
211
|
+
const bubble = trigger.closest<HTMLElement>('.group\\/bubble');
|
|
212
|
+
if (bubble) reposition(bubble);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Cierre accesible con tecla Escape
|
|
217
|
+
document.addEventListener('keydown', (e) => {
|
|
218
|
+
if (e.key === 'Escape') {
|
|
219
|
+
closeActiveBubble();
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Recalcular o cerrar en scroll/resize
|
|
224
|
+
window.addEventListener('resize', () => {
|
|
225
|
+
if (activeBubble) reposition(activeBubble);
|
|
226
|
+
}, { passive: true });
|
|
227
|
+
|
|
228
|
+
window.addEventListener('scroll', () => {
|
|
229
|
+
if (activeBubble) closeActiveBubble();
|
|
230
|
+
}, { passive: true });
|
|
115
231
|
}
|
|
116
232
|
|
|
117
|
-
|
|
118
|
-
document.
|
|
233
|
+
setupHelpTooltipSystem();
|
|
234
|
+
if (document.readyState === 'loading') {
|
|
235
|
+
document.addEventListener('DOMContentLoaded', setupHelpTooltipSystem);
|
|
236
|
+
}
|
|
237
|
+
document.addEventListener('astro:page-load', setupHelpTooltipSystem);
|
|
238
|
+
window.addEventListener('synthex:page-ready', setupHelpTooltipSystem);
|
|
119
239
|
</script>
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Preloader Vectorial Cinemático: Metamorfosis Geométrica al Logotipo Horizontal Synthex
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<div
|
|
6
|
+
id="preloader-curtain"
|
|
7
|
+
class="fixed inset-0 z-[9999] flex flex-col items-center justify-center bg-charcoal select-none overflow-hidden"
|
|
8
|
+
aria-hidden="true"
|
|
9
|
+
>
|
|
10
|
+
<div class="relative flex flex-col items-center justify-center p-8">
|
|
11
|
+
<!-- Contenedor Maestro SVG con Formas Geométricas que mutan al Logo Horizontal -->
|
|
12
|
+
<svg
|
|
13
|
+
id="preloader-master-svg"
|
|
14
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
15
|
+
viewBox="0 0 350 100"
|
|
16
|
+
class="w-72 sm:w-80 md:w-[420px] overflow-visible"
|
|
17
|
+
>
|
|
18
|
+
<defs>
|
|
19
|
+
<!-- Trazados Destino Ocultos: Isotipo Oficial </> en Verde Pistacho -->
|
|
20
|
+
<!-- 0: Bracket Izquierdo < -->
|
|
21
|
+
<path
|
|
22
|
+
id="target-bracket-left"
|
|
23
|
+
d="M 40 29 L 18 50 L 40 71 L 44.5 66.5 L 27 50 L 44.5 33.5 Z"
|
|
24
|
+
/>
|
|
25
|
+
<!-- 1: Barra Diagonal / -->
|
|
26
|
+
<path
|
|
27
|
+
id="target-slash"
|
|
28
|
+
d="M 50.5 70 L 64.5 30 L 68.5 31.5 L 54.5 71.5 Z"
|
|
29
|
+
/>
|
|
30
|
+
<!-- 2: Bracket Derecho > -->
|
|
31
|
+
<path
|
|
32
|
+
id="target-bracket-right"
|
|
33
|
+
d="M 74 29 L 96 50 L 74 71 L 69.5 66.5 L 87 50 L 69.5 33.5 Z"
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
<!-- Trazados Destino Ocultos: Glifos Tipográficos Outfit Bold de 'Synthex' -->
|
|
37
|
+
<!-- 3: S -->
|
|
38
|
+
<path
|
|
39
|
+
id="target-char-s"
|
|
40
|
+
d="M135.12 68.59L135.12 68.59Q130.42 68.59 127.02 67.08Q123.62 65.57 120.86 62.38L120.86 62.38L126.37 56.93Q128.21 59.09 130.42 60.22Q132.64 61.36 135.66 61.36L135.66 61.36Q138.36 61.36 139.84 60.39Q141.33 59.41 141.33 57.69L141.33 57.69Q141.33 55.90 140.03 54.82Q138.74 53.74 136.71 53.02Q134.69 52.29 132.39 51.45Q130.10 50.61 128.05 49.34Q125.99 48.07 124.72 45.97Q123.46 43.86 123.46 40.51L123.46 40.51Q123.46 37.00 125.16 34.49Q126.86 31.98 129.88 30.63Q132.91 29.28 136.85 29.28L136.85 29.28Q140.84 29.28 144.16 30.71Q147.49 32.14 149.65 34.52L149.65 34.52L144.14 39.97Q142.41 38.19 140.66 37.33Q138.90 36.46 136.69 36.46L136.69 36.46Q134.42 36.46 133.15 37.30Q131.88 38.14 131.88 39.70L131.88 39.70Q131.88 41.38 133.15 42.35Q134.42 43.32 136.47 44.05Q138.52 44.78 140.82 45.62Q143.11 46.45 145.14 47.78Q147.16 49.10 148.46 51.29Q149.75 53.47 149.75 56.93L149.75 56.93Q149.75 62.44 145.87 65.52Q141.98 68.59 135.12 68.59Z"
|
|
41
|
+
/>
|
|
42
|
+
<!-- 4: y -->
|
|
43
|
+
<path
|
|
44
|
+
id="target-char-y"
|
|
45
|
+
d="M164.23 79.07L155.75 79.07L161.69 66.22L151.70 41.76L160.61 41.76L165.85 57.74L171.19 41.76L180.10 41.76L168.87 68.11L164.23 79.07Z"
|
|
46
|
+
/>
|
|
47
|
+
<!-- 5: n -->
|
|
48
|
+
<path
|
|
49
|
+
id="target-char-n"
|
|
50
|
+
d="M191.50 68L183.23 68L183.23 41.76L191.50 41.76L191.50 43.86Q194.41 41.22 198.84 41.22L198.84 41.22Q201.70 41.22 203.97 42.59Q206.24 43.97 207.53 46.24Q208.83 48.51 208.83 51.21L208.83 51.21L208.83 68L200.57 68L200.57 53.04Q200.57 50.99 199.30 49.72Q198.03 48.45 196.09 48.45L196.09 48.45Q194.09 48.45 192.79 49.72Q191.50 50.99 191.50 53.04L191.50 53.04L191.50 68Z"
|
|
51
|
+
/>
|
|
52
|
+
<!-- 6: t -->
|
|
53
|
+
<path
|
|
54
|
+
id="target-char-t"
|
|
55
|
+
d="M226.11 68L217.85 68L217.85 48.78L211.91 48.78L211.91 41.76L217.85 41.76L217.85 30.90L226.11 30.90L226.11 41.76L232.05 41.76L232.05 48.78L226.11 48.78L226.11 68Z"
|
|
56
|
+
/>
|
|
57
|
+
<!-- 7: h -->
|
|
58
|
+
<path
|
|
59
|
+
id="target-char-h"
|
|
60
|
+
d="M243.93 68L235.67 68L235.67 28.80L243.93 28.80L243.93 43.70Q246.74 41.22 251.00 41.22L251.00 41.22Q254.03 41.22 256.35 42.48Q258.67 43.75 259.97 46.02Q261.26 48.29 261.26 51.21L261.26 51.21L261.26 68L253.00 68L253.00 53.04Q253.00 50.99 251.73 49.72Q250.46 48.45 248.52 48.45L248.52 48.45Q246.52 48.45 245.23 49.72Q243.93 50.99 243.93 53.04L243.93 53.04L243.93 68Z"
|
|
61
|
+
/>
|
|
62
|
+
<!-- 8: e -->
|
|
63
|
+
<path
|
|
64
|
+
id="target-char-e"
|
|
65
|
+
d="M279.52 68.59L279.52 68.59Q275.25 68.59 271.93 66.84Q268.61 65.08 266.72 61.98Q264.83 58.87 264.83 54.88L264.83 54.88Q264.83 50.94 266.69 47.86Q268.55 44.78 271.74 42.97Q274.93 41.16 278.92 41.16L278.92 41.16Q282.76 41.16 285.75 42.86Q288.75 44.56 290.45 47.51Q292.15 50.45 292.15 54.28L292.15 54.28Q292.15 55.74 291.77 57.58L291.77 57.58L272.98 57.63Q273.63 59.85 275.30 61.03Q276.98 62.22 279.46 62.22L279.46 62.22Q283.40 62.22 285.73 59.52L285.73 59.52L290.26 64.06Q288.32 66.33 285.56 67.46Q282.81 68.59 279.52 68.59ZM278.98 47.48L278.98 47.48Q276.71 47.48 275.14 48.67Q273.58 49.86 272.98 51.96L272.98 51.96L284.43 51.91Q283.40 47.48 278.98 47.48Z"
|
|
66
|
+
/>
|
|
67
|
+
<!-- 9: x -->
|
|
68
|
+
<path
|
|
69
|
+
id="target-char-x"
|
|
70
|
+
d="M302.52 68L293.50 68L302.90 54.61L293.99 41.76L303.65 41.76L308.03 48.88L312.46 41.76L321.42 41.76L312.67 54.45L321.96 68L312.40 68L307.54 60.17L302.52 68Z"
|
|
71
|
+
/>
|
|
72
|
+
</defs>
|
|
73
|
+
|
|
74
|
+
<!-- FORMAS GEOMÉTRICAS ELEMENTALES ACTIVAS (▲ ■ ●) QUE MUTAN AL LOGO -->
|
|
75
|
+
<g id="preloader-morph-group" class="opacity-0">
|
|
76
|
+
<!-- 0: Triángulo que muta al Bracket Izquierdo < (cx: 31, cy: 50) -->
|
|
77
|
+
<path
|
|
78
|
+
id="morph-shape-0"
|
|
79
|
+
class="morph-item"
|
|
80
|
+
d="M 18 50 L 44 32 L 44 68 Z"
|
|
81
|
+
fill="#E0F9B5"
|
|
82
|
+
/>
|
|
83
|
+
|
|
84
|
+
<!-- 1: Rectángulo vertical que muta a la Barra / (cx: 58, cy: 50) -->
|
|
85
|
+
<path
|
|
86
|
+
id="morph-shape-1"
|
|
87
|
+
class="morph-item"
|
|
88
|
+
d="M 54 30 L 63 30 L 63 70 L 54 70 Z"
|
|
89
|
+
fill="#E0F9B5"
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<!-- 2: Triángulo que muta al Bracket Derecho > (cx: 85, cy: 50) -->
|
|
93
|
+
<path
|
|
94
|
+
id="morph-shape-2"
|
|
95
|
+
class="morph-item"
|
|
96
|
+
d="M 96 50 L 70 68 L 70 32 Z"
|
|
97
|
+
fill="#E0F9B5"
|
|
98
|
+
/>
|
|
99
|
+
|
|
100
|
+
<!-- 3: Círculo que muta a 'S' (cx: 135, cy: 50, r: 16) -->
|
|
101
|
+
<path
|
|
102
|
+
id="morph-shape-3"
|
|
103
|
+
class="morph-item"
|
|
104
|
+
d="M 135 34 A 16 16 0 1 0 135 66 A 16 16 0 1 0 135 34 Z"
|
|
105
|
+
fill="#FFFFFF"
|
|
106
|
+
/>
|
|
107
|
+
|
|
108
|
+
<!-- 4: Triángulo invertido que muta a 'y' (cx: 166, cy: 55) -->
|
|
109
|
+
<path
|
|
110
|
+
id="morph-shape-4"
|
|
111
|
+
class="morph-item"
|
|
112
|
+
d="M 152 40 L 180 40 L 166 75 Z"
|
|
113
|
+
fill="#FFFFFF"
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
<!-- 5: Cuadrado que muta a 'n' (cx: 196, cy: 54, w: 26, h: 26) -->
|
|
117
|
+
<path
|
|
118
|
+
id="morph-shape-5"
|
|
119
|
+
class="morph-item"
|
|
120
|
+
d="M 183 41 L 209 41 L 209 67 L 183 67 Z"
|
|
121
|
+
fill="#FFFFFF"
|
|
122
|
+
/>
|
|
123
|
+
|
|
124
|
+
<!-- 6: Rectángulo vertical que muta a 't' (cx: 222, cy: 50) -->
|
|
125
|
+
<path
|
|
126
|
+
id="morph-shape-6"
|
|
127
|
+
class="morph-item"
|
|
128
|
+
d="M 215 31 L 229 31 L 229 68 L 215 68 Z"
|
|
129
|
+
fill="#FFFFFF"
|
|
130
|
+
/>
|
|
131
|
+
|
|
132
|
+
<!-- 7: Cuadrado alto que muta a 'h' (cx: 248, cy: 49) -->
|
|
133
|
+
<path
|
|
134
|
+
id="morph-shape-7"
|
|
135
|
+
class="morph-item"
|
|
136
|
+
d="M 235 29 L 261 29 L 261 68 L 235 68 Z"
|
|
137
|
+
fill="#FFFFFF"
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<!-- 8: Círculo que muta a 'e' (cx: 278, cy: 55, r: 14) -->
|
|
141
|
+
<path
|
|
142
|
+
id="morph-shape-8"
|
|
143
|
+
class="morph-item"
|
|
144
|
+
d="M 278 41 A 14 14 0 1 0 278 69 A 14 14 0 1 0 278 41 Z"
|
|
145
|
+
fill="#FFFFFF"
|
|
146
|
+
/>
|
|
147
|
+
|
|
148
|
+
<!-- 9: Rombo / Diamante que muta a 'x' (cx: 308, cy: 55, r: 14) -->
|
|
149
|
+
<path
|
|
150
|
+
id="morph-shape-9"
|
|
151
|
+
class="morph-item"
|
|
152
|
+
d="M 308 41 L 322 55 L 308 69 L 294 55 Z"
|
|
153
|
+
fill="#FFFFFF"
|
|
154
|
+
/>
|
|
155
|
+
</g>
|
|
156
|
+
</svg>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<script>
|
|
161
|
+
import gsap from 'gsap';
|
|
162
|
+
import { MorphSVGPlugin } from 'gsap/MorphSVGPlugin';
|
|
163
|
+
|
|
164
|
+
gsap.registerPlugin(MorphSVGPlugin);
|
|
165
|
+
|
|
166
|
+
const curtain = document.getElementById('preloader-curtain');
|
|
167
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
168
|
+
const alreadySeen = sessionStorage.getItem('synthex_preloaded_session');
|
|
169
|
+
|
|
170
|
+
function notifyPageReady() {
|
|
171
|
+
(window as any).__synthexPageReady = true;
|
|
172
|
+
window.dispatchEvent(new CustomEvent('synthex:page-ready'));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (curtain) {
|
|
176
|
+
if (prefersReducedMotion || alreadySeen) {
|
|
177
|
+
curtain.style.display = 'none';
|
|
178
|
+
document.documentElement.classList.add('synthex-preloaded');
|
|
179
|
+
requestAnimationFrame(() => {
|
|
180
|
+
notifyPageReady();
|
|
181
|
+
});
|
|
182
|
+
} else {
|
|
183
|
+
const morphGroup = document.getElementById('preloader-morph-group');
|
|
184
|
+
const targets = [
|
|
185
|
+
'#target-bracket-left',
|
|
186
|
+
'#target-slash',
|
|
187
|
+
'#target-bracket-right',
|
|
188
|
+
'#target-char-s',
|
|
189
|
+
'#target-char-y',
|
|
190
|
+
'#target-char-n',
|
|
191
|
+
'#target-char-t',
|
|
192
|
+
'#target-char-h',
|
|
193
|
+
'#target-char-e',
|
|
194
|
+
'#target-char-x',
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
const tl = gsap.timeline({
|
|
198
|
+
onComplete: () => {
|
|
199
|
+
// Desplegar suavemente el telón hacia arriba
|
|
200
|
+
gsap.to(curtain, {
|
|
201
|
+
yPercent: -100,
|
|
202
|
+
duration: 0.7,
|
|
203
|
+
ease: 'power4.inOut',
|
|
204
|
+
onStart: () => {
|
|
205
|
+
notifyPageReady();
|
|
206
|
+
},
|
|
207
|
+
onComplete: () => {
|
|
208
|
+
curtain.style.display = 'none';
|
|
209
|
+
sessionStorage.setItem('synthex_preloaded_session', 'true');
|
|
210
|
+
document.documentElement.classList.add('synthex-preloaded');
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// 1. Entrada sutil de las figuras geométricas elementales (▲ ■ ●)
|
|
217
|
+
tl.to(morphGroup, {
|
|
218
|
+
opacity: 1,
|
|
219
|
+
duration: 0.35,
|
|
220
|
+
ease: 'power2.out',
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// 2. Metamorfosis geométrica con MorphSVG (cada figura transmuta al glifo oficial)
|
|
224
|
+
targets.forEach((targetSelector, index) => {
|
|
225
|
+
tl.to(
|
|
226
|
+
`#morph-shape-${index}`,
|
|
227
|
+
{
|
|
228
|
+
morphSVG: targetSelector,
|
|
229
|
+
duration: 0.85,
|
|
230
|
+
ease: 'power2.inOut',
|
|
231
|
+
},
|
|
232
|
+
0.2 + index * 0.035
|
|
233
|
+
);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// 3. Breve pausa ceremonial tras completarse el logotipo
|
|
237
|
+
tl.to({}, { duration: 0.35 });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
</script>
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
interface Props {
|
|
3
|
+
as?: 'h1' | 'h2' | 'h3' | 'span';
|
|
3
4
|
prefixText?: string;
|
|
4
5
|
highlightText?: string;
|
|
5
6
|
strokeColor?: string;
|
|
6
7
|
className?: string;
|
|
8
|
+
headingClass?: string;
|
|
7
9
|
prefixI18nKey?: string;
|
|
8
10
|
highlightI18nKey?: string;
|
|
9
11
|
id?: string;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
const {
|
|
15
|
+
as: Tag = 'h2',
|
|
13
16
|
prefixText = "Ingeniería con",
|
|
14
17
|
highlightText = "total transparencia.",
|
|
15
18
|
strokeColor = "#E0F9B5",
|
|
16
19
|
className = "",
|
|
20
|
+
headingClass = "text-2xl sm:text-3xl md:text-4xl font-display font-bold text-white tracking-tight leading-snug",
|
|
17
21
|
prefixI18nKey,
|
|
18
22
|
highlightI18nKey,
|
|
19
23
|
id = "wavy-heading-" + Math.random().toString(36).substring(2, 7),
|
|
@@ -21,15 +25,15 @@ const {
|
|
|
21
25
|
---
|
|
22
26
|
|
|
23
27
|
<div class={`w-full text-center ${className}`}>
|
|
24
|
-
<
|
|
28
|
+
<Tag class={headingClass}>
|
|
25
29
|
{prefixText && (
|
|
26
|
-
<span data-i18n={prefixI18nKey}>{prefixText}</span>
|
|
30
|
+
<span class="inline relative z-10" data-i18n={prefixI18nKey}>{prefixText}</span>
|
|
27
31
|
)}{" "}
|
|
28
|
-
<span class="
|
|
32
|
+
<span class="services-hero-highlight inline-block relative text-pistachio">
|
|
29
33
|
<span class="relative z-10" data-i18n={highlightI18nKey}>{highlightText}</span>
|
|
30
34
|
<svg
|
|
31
35
|
id={`${id}-svg`}
|
|
32
|
-
class="wavy-underline-svg absolute left-0 -bottom-2 w-full h-3 sm:h-4 overflow-visible pointer-events-none"
|
|
36
|
+
class="wavy-underline-svg absolute left-0 -bottom-2 sm:-bottom-3 w-full h-3 sm:h-4 overflow-visible pointer-events-none z-10"
|
|
33
37
|
style="opacity: 0; visibility: hidden;"
|
|
34
38
|
viewBox="0 0 300 16"
|
|
35
39
|
preserveAspectRatio="none"
|
|
@@ -47,7 +51,7 @@ const {
|
|
|
47
51
|
/>
|
|
48
52
|
</svg>
|
|
49
53
|
</span>
|
|
50
|
-
</
|
|
54
|
+
</Tag>
|
|
51
55
|
</div>
|
|
52
56
|
|
|
53
57
|
<script>
|
|
@@ -58,6 +62,9 @@ const {
|
|
|
58
62
|
const svgs = document.querySelectorAll<SVGSVGElement>('.wavy-underline-svg');
|
|
59
63
|
|
|
60
64
|
svgs.forEach((svg) => {
|
|
65
|
+
if ((svg as any).__wavyBound) return;
|
|
66
|
+
(svg as any).__wavyBound = true;
|
|
67
|
+
|
|
61
68
|
const path = svg.querySelector<SVGPathElement>('.wavy-underline-path');
|
|
62
69
|
if (!path) return;
|
|
63
70
|
|
|
@@ -87,4 +94,5 @@ const {
|
|
|
87
94
|
|
|
88
95
|
initWavyHeadings();
|
|
89
96
|
document.addEventListener('astro:page-load', initWavyHeadings);
|
|
97
|
+
window.addEventListener('synthex:page-ready', initWavyHeadings);
|
|
90
98
|
</script>
|
package/dist/astro/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export const ButtonOutline: any;
|
|
|
2
2
|
export const ButtonPrimary: any;
|
|
3
3
|
export const ButtonSecondary: any;
|
|
4
4
|
export const ClientTrustCard: any;
|
|
5
|
+
export const FooterBounceCurve: any;
|
|
6
|
+
export const Preloader: any;
|
|
5
7
|
export const HelpTooltip: any;
|
|
6
8
|
export const LanguageSelectorPill: any;
|
|
7
9
|
export const ProcessStepCard: any;
|
package/dist/astro/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export { default as ButtonOutline } from './components/ButtonOutline.astro';
|
|
|
2
2
|
export { default as ButtonPrimary } from './components/ButtonPrimary.astro';
|
|
3
3
|
export { default as ButtonSecondary } from './components/ButtonSecondary.astro';
|
|
4
4
|
export { default as ClientTrustCard } from './components/ClientTrustCard.astro';
|
|
5
|
+
export { default as FooterBounceCurve } from './components/FooterBounceCurve.astro';
|
|
6
|
+
export { default as Preloader } from './components/Preloader.astro';
|
|
5
7
|
export { default as HelpTooltip } from './components/HelpTooltip.astro';
|
|
6
8
|
export { default as LanguageSelectorPill } from './components/LanguageSelectorPill.astro';
|
|
7
9
|
export { default as ProcessStepCard } from './components/ProcessStepCard.astro';
|