@xscriptor/xcomponents 0.1.0 → 0.1.1
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/README.md +1 -0
- package/dist/{chunk-U27ZVCP7.mjs → chunk-2H7TVDE7.mjs} +14 -2
- package/dist/chunk-2H7TVDE7.mjs.map +7 -0
- package/dist/{chunk-5G4P2E76.mjs → chunk-34NJCJUI.mjs} +11 -2
- package/dist/chunk-34NJCJUI.mjs.map +7 -0
- package/dist/chunk-FZRTAML3.mjs +1 -1
- package/dist/chunk-FZRTAML3.mjs.map +7 -1
- package/dist/{chunk-2OAXRRVQ.mjs → chunk-MYFPSHSQ.mjs} +32 -3
- package/dist/chunk-MYFPSHSQ.mjs.map +7 -0
- package/dist/{chunk-NY22GB3E.mjs → chunk-TG3B4GAW.mjs} +26 -2
- package/dist/chunk-TG3B4GAW.mjs.map +7 -0
- package/dist/{chunk-QCMWPIG7.mjs → chunk-TKT37LIX.mjs} +39 -3
- package/dist/chunk-TKT37LIX.mjs.map +7 -0
- package/dist/{chunk-42XPBYTL.mjs → chunk-UROP4J6G.mjs} +29 -4
- package/dist/chunk-UROP4J6G.mjs.map +7 -0
- package/dist/components/content/index.css +23 -23
- package/dist/components/content/index.css.map +7 -1
- package/dist/components/content/index.d.ts +2 -17
- package/dist/components/content/index.js +11 -6
- package/dist/components/content/index.js.map +7 -1
- package/dist/components/content/index.mjs +2 -2
- package/dist/components/content/index.mjs.map +7 -1
- package/dist/components/content/xinteractivephrase/XInteractivePhrase.d.ts +13 -0
- package/dist/components/content/xinteractivephrase/index.d.ts +3 -0
- package/dist/components/forms/index.css +54 -54
- package/dist/components/forms/index.css.map +7 -1
- package/dist/components/forms/index.d.ts +4 -68
- package/dist/components/forms/index.js +39 -8
- package/dist/components/forms/index.js.map +7 -1
- package/dist/components/forms/index.mjs +2 -2
- package/dist/components/forms/index.mjs.map +7 -1
- package/dist/components/forms/xcontactform/XContactForm.d.ts +42 -0
- package/dist/components/forms/xcontactform/index.d.ts +3 -0
- package/dist/components/forms/xnewsletter/XNewsletter.d.ts +21 -0
- package/dist/components/forms/xnewsletter/index.d.ts +3 -0
- package/dist/components/gallery/index.css +58 -58
- package/dist/components/gallery/index.css.map +7 -1
- package/dist/components/gallery/index.d.ts +4 -29
- package/dist/components/gallery/index.js +32 -8
- package/dist/components/gallery/index.js.map +7 -1
- package/dist/components/gallery/index.mjs +2 -2
- package/dist/components/gallery/index.mjs.map +7 -1
- package/dist/components/gallery/xmicrogallerytext/XMicroGalleryText.d.ts +15 -0
- package/dist/components/gallery/xmicrogallerytext/index.d.ts +3 -0
- package/dist/components/gallery/xstaticgallery/XStaticGallery.d.ts +10 -0
- package/dist/components/gallery/xstaticgallery/index.d.ts +3 -0
- package/dist/components/index.css +215 -215
- package/dist/components/index.css.map +7 -1
- package/dist/components/index.d.ts +6 -8
- package/dist/components/index.js +146 -31
- package/dist/components/index.js.map +7 -1
- package/dist/components/index.mjs +12 -12
- package/dist/components/index.mjs.map +7 -1
- package/dist/components/layout/index.css +28 -28
- package/dist/components/layout/index.css.map +7 -1
- package/dist/components/layout/index.d.ts +6 -55
- package/dist/components/layout/index.js +29 -10
- package/dist/components/layout/index.js.map +7 -1
- package/dist/components/layout/index.mjs +2 -2
- package/dist/components/layout/index.mjs.map +7 -1
- package/dist/components/layout/xfooter/XFooter.d.ts +24 -0
- package/dist/components/layout/xfooter/index.d.ts +3 -0
- package/dist/components/layout/xseparator/XSeparator.d.ts +13 -0
- package/dist/components/layout/xseparator/index.d.ts +3 -0
- package/dist/components/layout/xzigzaglayout/XZigZagLayout.d.ts +12 -0
- package/dist/components/layout/xzigzaglayout/index.d.ts +3 -0
- package/dist/components/navigation/index.css +35 -35
- package/dist/components/navigation/index.css.map +7 -1
- package/dist/components/navigation/index.d.ts +2 -76
- package/dist/components/navigation/index.js +26 -6
- package/dist/components/navigation/index.js.map +7 -1
- package/dist/components/navigation/index.mjs +2 -2
- package/dist/components/navigation/index.mjs.map +7 -1
- package/dist/components/navigation/{index.d.mts → xnavbar/XNavbar.d.ts} +6 -10
- package/dist/components/navigation/xnavbar/index.d.ts +3 -0
- package/dist/components/social/index.css +22 -22
- package/dist/components/social/index.css.map +7 -1
- package/dist/components/social/index.d.ts +2 -55
- package/dist/components/social/index.js +14 -13
- package/dist/components/social/index.js.map +7 -1
- package/dist/components/social/index.mjs +2 -2
- package/dist/components/social/index.mjs.map +7 -1
- package/dist/components/social/xsocialcontact/XSocialContact.d.ts +30 -0
- package/dist/components/social/xsocialcontact/XSocialIcons.d.ts +21 -0
- package/dist/components/social/xsocialcontact/index.d.ts +5 -0
- package/dist/index.css +215 -215
- package/dist/index.css.map +7 -1
- package/dist/index.d.ts +1 -8
- package/dist/index.js +149 -34
- package/dist/index.js.map +7 -1
- package/dist/index.mjs +12 -12
- package/dist/index.mjs.map +7 -1
- package/package.json +6 -4
- package/dist/chunk-2OAXRRVQ.mjs.map +0 -1
- package/dist/chunk-42XPBYTL.mjs.map +0 -1
- package/dist/chunk-5G4P2E76.mjs.map +0 -1
- package/dist/chunk-NY22GB3E.mjs.map +0 -1
- package/dist/chunk-QCMWPIG7.mjs.map +0 -1
- package/dist/chunk-U27ZVCP7.mjs.map +0 -1
- package/dist/components/content/index.d.mts +0 -17
- package/dist/components/forms/index.d.mts +0 -68
- package/dist/components/gallery/index.d.mts +0 -29
- package/dist/components/index.d.mts +0 -8
- package/dist/components/layout/index.d.mts +0 -55
- package/dist/components/social/index.d.mts +0 -55
- package/dist/index.d.mts +0 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* src/components/navigation/xnavbar/XNavbar.module.css */
|
|
2
|
-
.
|
|
2
|
+
.XNavbar_header3 {
|
|
3
3
|
height: 100%;
|
|
4
4
|
display: flex;
|
|
5
5
|
align-items: center;
|
|
@@ -11,26 +11,26 @@
|
|
|
11
11
|
z-index: 60;
|
|
12
12
|
}
|
|
13
13
|
@media (min-width: 640px) {
|
|
14
|
-
.
|
|
14
|
+
.XNavbar_header3 {
|
|
15
15
|
padding-inline: 2rem;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
@media (min-width: 768px) {
|
|
19
|
-
.
|
|
19
|
+
.XNavbar_header3 {
|
|
20
20
|
padding-inline: 3rem;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
@media (min-width: 1024px) {
|
|
24
|
-
.
|
|
24
|
+
.XNavbar_header3 {
|
|
25
25
|
padding-inline: 5rem;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
@media (min-width: 1280px) {
|
|
29
|
-
.
|
|
29
|
+
.XNavbar_header3 {
|
|
30
30
|
padding-inline: 12rem;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
.
|
|
33
|
+
.XNavbar_desktopNav3 {
|
|
34
34
|
display: none;
|
|
35
35
|
align-items: center;
|
|
36
36
|
width: 100%;
|
|
@@ -38,35 +38,35 @@
|
|
|
38
38
|
padding-bottom: 0.5rem;
|
|
39
39
|
}
|
|
40
40
|
@media (min-width: 768px) {
|
|
41
|
-
.
|
|
41
|
+
.XNavbar_desktopNav3 {
|
|
42
42
|
display: grid;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
.
|
|
46
|
-
.
|
|
45
|
+
.XNavbar_desktopLinksLeft3,
|
|
46
|
+
.XNavbar_desktopLinksRight3 {
|
|
47
47
|
display: flex;
|
|
48
48
|
align-items: center;
|
|
49
49
|
gap: 1.5rem;
|
|
50
50
|
min-width: 0;
|
|
51
51
|
}
|
|
52
|
-
.
|
|
52
|
+
.XNavbar_desktopLinksLeft3 {
|
|
53
53
|
justify-content: flex-end;
|
|
54
54
|
}
|
|
55
|
-
.
|
|
55
|
+
.XNavbar_desktopLinksRight3 {
|
|
56
56
|
justify-content: flex-start;
|
|
57
57
|
}
|
|
58
|
-
.
|
|
58
|
+
.XNavbar_logoSlot3 {
|
|
59
59
|
display: flex;
|
|
60
60
|
justify-content: center;
|
|
61
61
|
align-items: center;
|
|
62
62
|
}
|
|
63
|
-
.
|
|
63
|
+
.XNavbar_logoWrapper3 {
|
|
64
64
|
position: relative;
|
|
65
65
|
margin-inline: 1rem;
|
|
66
66
|
display: flex;
|
|
67
67
|
align-items: center;
|
|
68
68
|
}
|
|
69
|
-
.
|
|
69
|
+
.XNavbar_logoBtn3 {
|
|
70
70
|
font-weight: 700;
|
|
71
71
|
font-size: 1.5rem;
|
|
72
72
|
line-height: 1;
|
|
@@ -77,21 +77,21 @@
|
|
|
77
77
|
color: var(--text);
|
|
78
78
|
padding: 0;
|
|
79
79
|
}
|
|
80
|
-
.
|
|
80
|
+
.XNavbar_iconTray3 {
|
|
81
81
|
position: absolute;
|
|
82
82
|
top: 50%;
|
|
83
83
|
transform: translateY(-50%);
|
|
84
84
|
pointer-events: none;
|
|
85
85
|
}
|
|
86
|
-
.
|
|
86
|
+
.XNavbar_iconTrayRight3 {
|
|
87
87
|
left: 100%;
|
|
88
88
|
padding-left: 0.75rem;
|
|
89
89
|
}
|
|
90
|
-
.
|
|
90
|
+
.XNavbar_iconTrayLeft3 {
|
|
91
91
|
right: 100%;
|
|
92
92
|
padding-right: 0.75rem;
|
|
93
93
|
}
|
|
94
|
-
.
|
|
94
|
+
.XNavbar_navLink3 {
|
|
95
95
|
padding: 0.25rem;
|
|
96
96
|
border-bottom: 2px solid transparent;
|
|
97
97
|
transition:
|
|
@@ -102,30 +102,30 @@
|
|
|
102
102
|
text-decoration: none;
|
|
103
103
|
white-space: nowrap;
|
|
104
104
|
}
|
|
105
|
-
.
|
|
105
|
+
.XNavbar_navLink3:hover {
|
|
106
106
|
color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));
|
|
107
107
|
opacity: var(--xnav-link-hover-opacity, 0.7);
|
|
108
108
|
}
|
|
109
|
-
.
|
|
109
|
+
.XNavbar_navLinkActive3 {
|
|
110
110
|
border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));
|
|
111
111
|
font-weight: 600;
|
|
112
112
|
}
|
|
113
|
-
.
|
|
113
|
+
.XNavbar_navLinkExternal3::after {
|
|
114
114
|
content: " \2197";
|
|
115
115
|
font-size: 0.7em;
|
|
116
116
|
opacity: 0.6;
|
|
117
117
|
}
|
|
118
|
-
.
|
|
118
|
+
.XNavbar_mobileToggle3 {
|
|
119
119
|
display: flex;
|
|
120
120
|
align-items: center;
|
|
121
121
|
justify-content: center;
|
|
122
122
|
}
|
|
123
123
|
@media (min-width: 768px) {
|
|
124
|
-
.
|
|
124
|
+
.XNavbar_mobileToggle3 {
|
|
125
125
|
display: none;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
.
|
|
128
|
+
.XNavbar_hamburgerBtn3 {
|
|
129
129
|
width: 2.5rem;
|
|
130
130
|
height: 2rem;
|
|
131
131
|
display: flex;
|
|
@@ -139,13 +139,13 @@
|
|
|
139
139
|
z-index: 80;
|
|
140
140
|
padding: 0;
|
|
141
141
|
}
|
|
142
|
-
.
|
|
142
|
+
.XNavbar_bar3 {
|
|
143
143
|
width: var(--xnav-bar-w, 2rem);
|
|
144
144
|
height: var(--xnav-bar-h, 3px);
|
|
145
145
|
background: var(--xnav-bar-color, var(--text));
|
|
146
146
|
border-radius: 2px;
|
|
147
147
|
}
|
|
148
|
-
.
|
|
148
|
+
.XNavbar_mobileOverlay3 {
|
|
149
149
|
position: fixed;
|
|
150
150
|
inset: 0;
|
|
151
151
|
width: 100vw;
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
font-size: 2.5rem;
|
|
161
161
|
z-index: 9999;
|
|
162
162
|
}
|
|
163
|
-
.
|
|
163
|
+
.XNavbar_mobileCloseBtn3 {
|
|
164
164
|
position: fixed;
|
|
165
165
|
top: 2rem;
|
|
166
166
|
left: 1rem;
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
z-index: 10000;
|
|
177
177
|
-webkit-tap-highlight-color: transparent;
|
|
178
178
|
}
|
|
179
|
-
.
|
|
179
|
+
.XNavbar_closeBar3 {
|
|
180
180
|
display: block;
|
|
181
181
|
position: absolute;
|
|
182
182
|
width: 2rem;
|
|
@@ -184,13 +184,13 @@
|
|
|
184
184
|
border-radius: 2px;
|
|
185
185
|
background: currentColor;
|
|
186
186
|
}
|
|
187
|
-
.
|
|
187
|
+
.XNavbar_mobileLogo3 {
|
|
188
188
|
font-weight: 700;
|
|
189
189
|
font-size: 3rem;
|
|
190
190
|
user-select: none;
|
|
191
191
|
pointer-events: none;
|
|
192
192
|
}
|
|
193
|
-
.
|
|
193
|
+
.XNavbar_mobileNavLink3 {
|
|
194
194
|
font-size: 2.5rem;
|
|
195
195
|
color: var(--xnav-link-color, var(--text));
|
|
196
196
|
text-decoration: none;
|
|
@@ -201,15 +201,15 @@
|
|
|
201
201
|
opacity 0.2s;
|
|
202
202
|
padding: 0.25rem;
|
|
203
203
|
}
|
|
204
|
-
.
|
|
204
|
+
.XNavbar_mobileNavLink3:hover {
|
|
205
205
|
color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));
|
|
206
206
|
opacity: var(--xnav-link-hover-opacity, 0.7);
|
|
207
207
|
}
|
|
208
|
-
.
|
|
208
|
+
.XNavbar_mobileNavLinkActive3 {
|
|
209
209
|
font-weight: 600;
|
|
210
210
|
border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));
|
|
211
211
|
}
|
|
212
|
-
.
|
|
212
|
+
.XNavbar_themeToggleMobile3 {
|
|
213
213
|
margin-top: 1rem;
|
|
214
214
|
font-size: 1rem;
|
|
215
215
|
padding: 0.5rem 1rem;
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
cursor: pointer;
|
|
224
224
|
transition: opacity 0.2s;
|
|
225
225
|
}
|
|
226
|
-
.
|
|
226
|
+
.XNavbar_themeToggleMobile3:hover {
|
|
227
227
|
opacity: 0.7;
|
|
228
228
|
}
|
|
229
|
-
/*# sourceMappingURL=index.css.map */
|
|
229
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/components/navigation/xnavbar/XNavbar.module.css"],
|
|
4
|
+
"sourcesContent": ["/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n XNavbar.module.css\n Navbar completamente libre de Tailwind.\n Usa variables CSS del tema global (--bg, --text, --border, --accent).\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* \u2500\u2500 Header / contenedor ra\u00EDz \u2500\u2500 */\n.header {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2rem 3rem;\n background: var(--bg);\n color: var(--text);\n font-size: 1.25rem;\n z-index: 60;\n}\n\n@media (min-width: 640px) { .header { padding-inline: 2rem; } }\n@media (min-width: 768px) { .header { padding-inline: 3rem; } }\n@media (min-width: 1024px) { .header { padding-inline: 5rem; } }\n@media (min-width: 1280px) { .header { padding-inline: 12rem; } }\n\n/* \u2500\u2500 Desktop nav \u2500\u2500 */\n.desktopNav {\n display: none;\n align-items: center;\n width: 100%;\n grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\n padding-bottom: 0.5rem;\n}\n\n@media (min-width: 768px) {\n .desktopNav {\n display: grid;\n }\n}\n\n.desktopLinksLeft,\n.desktopLinksRight {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n min-width: 0;\n}\n\n.desktopLinksLeft {\n justify-content: flex-end;\n}\n\n.desktopLinksRight {\n justify-content: flex-start;\n}\n\n.logoSlot {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* \u2500\u2500 Logo / bot\u00F3n central (desktop) \u2500\u2500 */\n.logoWrapper {\n position: relative;\n margin-inline: 1rem;\n display: flex;\n align-items: center;\n}\n\n.logoBtn {\n font-weight: 700;\n font-size: 1.5rem;\n line-height: 1;\n user-select: none;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text);\n padding: 0;\n}\n\n/* \u2500\u2500 Tray de \u00EDconos hover (sun/moon) \u2500\u2500 */\n.iconTray {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n.iconTrayRight {\n left: 100%;\n padding-left: 0.75rem;\n}\n\n.iconTrayLeft {\n right: 100%;\n padding-right: 0.75rem;\n}\n\n/* \u2500\u2500 NavLink (desktop) \u2500\u2500 */\n.navLink {\n padding: 0.25rem;\n border-bottom: 2px solid transparent;\n transition: border-color 0.2s, opacity 0.2s, color 0.2s;\n color: var(--xnav-link-color, var(--text));\n text-decoration: none;\n white-space: nowrap;\n}\n\n.navLink:hover {\n color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));\n opacity: var(--xnav-link-hover-opacity, 0.7);\n}\n\n.navLinkActive {\n border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));\n font-weight: 600;\n}\n\n/* External link indicator */\n.navLinkExternal::after {\n content: \" \u2197\";\n font-size: 0.7em;\n opacity: 0.6;\n}\n\n/* \u2500\u2500 Mobile hamburger \u2500\u2500 */\n.mobileToggle {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n@media (min-width: 768px) {\n .mobileToggle {\n display: none;\n }\n}\n\n.hamburgerBtn {\n width: 2.5rem;\n height: 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: space-between;\n background: none;\n border: none;\n cursor: pointer;\n position: relative;\n z-index: 80;\n padding: 0;\n}\n\n.bar {\n width: var(--xnav-bar-w, 2rem);\n height: var(--xnav-bar-h, 3px);\n background: var(--xnav-bar-color, var(--text));\n border-radius: 2px;\n}\n\n/* \u2500\u2500 Mobile overlay (portal) \u2500\u2500 */\n.mobileOverlay {\n position: fixed;\n inset: 0;\n width: 100vw;\n height: 100svh;\n background: var(--bg);\n color: var(--text);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2rem;\n font-size: 2.5rem;\n z-index: 9999;\n}\n\n.mobileCloseBtn {\n position: fixed;\n top: 2rem;\n left: 1rem;\n width: 2.5rem;\n height: 2rem;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n /* hereda el mismo color que las barras del hamburguesa */\n color: var(--xnav-bar-color, var(--text));\n z-index: 10000;\n -webkit-tap-highlight-color: transparent;\n}\n\n.closeBar {\n display: block;\n position: absolute;\n width: 2rem;\n height: 3px;\n border-radius: 2px;\n background: currentColor;\n}\n\n.mobileLogo {\n font-weight: 700;\n font-size: 3rem;\n user-select: none;\n pointer-events: none;\n}\n\n.mobileNavLink {\n font-size: 2.5rem;\n color: var(--xnav-link-color, var(--text));\n text-decoration: none;\n border-bottom: 2px solid transparent;\n transition: border-color 0.2s, color 0.2s, opacity 0.2s;\n padding: 0.25rem;\n}\n\n.mobileNavLink:hover {\n color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));\n opacity: var(--xnav-link-hover-opacity, 0.7);\n}\n\n.mobileNavLinkActive {\n font-weight: 600;\n border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));\n}\n\n/* \u2500\u2500 Bot\u00F3n tema (m\u00F3vil) \u2500\u2500 */\n.themeToggleMobile {\n margin-top: 1rem;\n font-size: 1rem;\n padding: 0.5rem 1rem;\n border: 1px solid var(--border);\n border-radius: 0.375rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: none;\n color: var(--text);\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n.themeToggleMobile:hover {\n opacity: 0.7;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["header", "desktopNav", "desktopLinksLeft", "desktopLinksRight", "logoSlot", "logoWrapper", "logoBtn", "iconTray", "iconTrayRight", "iconTrayLeft", "navLink", "navLinkActive", "navLinkExternal", "mobileToggle", "hamburgerBtn", "bar", "mobileOverlay", "mobileCloseBtn", "closeBar", "mobileLogo", "mobileNavLink", "mobileNavLinkActive", "themeToggleMobile"]
|
|
7
|
+
}
|
|
@@ -1,76 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type NavLinkItem = {
|
|
5
|
-
/** Ruta destino */
|
|
6
|
-
url: string;
|
|
7
|
-
/** Texto visible */
|
|
8
|
-
title: string;
|
|
9
|
-
/** Si es true abre en pestaña nueva y muestra el indicador ↗ */
|
|
10
|
-
external?: boolean;
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* ReactNode estático O función de render (size, color?) => ReactNode.
|
|
14
|
-
* La función recibe el tamaño y el color vigente para que el ícono
|
|
15
|
-
* pueda adaptarse dinámicamente a los props del navbar.
|
|
16
|
-
*/
|
|
17
|
-
type IconRenderer = ReactNode | ((size: number, color?: string) => ReactNode);
|
|
18
|
-
type ThemeToggleIcons = {
|
|
19
|
-
/** Ícono/renderer hacia tema oscuro (ReactNode o función) */
|
|
20
|
-
toDark: IconRenderer;
|
|
21
|
-
/** Ícono/renderer hacia tema claro (ReactNode o función) */
|
|
22
|
-
toLight: IconRenderer;
|
|
23
|
-
};
|
|
24
|
-
type XNavbarProps = {
|
|
25
|
-
/** Links que aparecen a la izquierda del logo en desktop */
|
|
26
|
-
linksLeft?: NavLinkItem[];
|
|
27
|
-
/** Links que aparecen a la derecha del logo en desktop */
|
|
28
|
-
linksRight?: NavLinkItem[];
|
|
29
|
-
/** Contenido del botón central (texto o JSX). Por defecto: "X" */
|
|
30
|
-
logo?: ReactNode;
|
|
31
|
-
/** Si true el logo actúa como toggle de tema (comportamiento original). Default: true */
|
|
32
|
-
logoAsThemeToggle?: boolean;
|
|
33
|
-
/** Callback custom si logoAsThemeToggle es false */
|
|
34
|
-
onLogoClick?: () => void;
|
|
35
|
-
/** Íconos para el toggle de tema. Si no se pasa, no se mostrará hint de ícono */
|
|
36
|
-
themeIcons?: ThemeToggleIcons;
|
|
37
|
-
/** Tema inicial. Default: "light" */
|
|
38
|
-
defaultTheme?: "light" | "dark";
|
|
39
|
-
/** Key de localStorage para persistencia del tema. Default: "theme" */
|
|
40
|
-
storageKey?: string;
|
|
41
|
-
/** Color base de los enlaces (Inicio, Contacto, etc.). Default: var(--text) */
|
|
42
|
-
linkColor?: string;
|
|
43
|
-
/** Color al hacer hover sobre los enlaces. Default: opacidad reducida del linkColor */
|
|
44
|
-
linkHoverColor?: string;
|
|
45
|
-
/** Color del borde inferior del enlace activo. Default: linkColor */
|
|
46
|
-
linkActiveColor?: string;
|
|
47
|
-
/** Color base de los íconos. Acepta cualquier valor CSS: hex, hsl, "var(--accent)", etc.
|
|
48
|
-
* Si no se pasa, los íconos heredan el color del texto (currentColor). */
|
|
49
|
-
iconColor?: string;
|
|
50
|
-
/** Color que toman los íconos al hacer hover sobre el logo. Default: iconColor */
|
|
51
|
-
iconHoverColor?: string;
|
|
52
|
-
/** Tamaño en px que se pasa a IconRenderer cuando es función. Default: 22 */
|
|
53
|
-
iconSize?: number;
|
|
54
|
-
/** Color de las 3 barras (y la X de cierre móvil). Acepta cualquier valor CSS. Default: var(--text) */
|
|
55
|
-
hamburgerColor?: string;
|
|
56
|
-
/** Ancho de las barras. Cualquier unidad CSS. Default: "2rem" */
|
|
57
|
-
hamburgerBarWidth?: string;
|
|
58
|
-
/** Grosor (altura) de las barras. Cualquier unidad CSS. Default: "3px" */
|
|
59
|
-
hamburgerBarThickness?: string;
|
|
60
|
-
/** Inyecta variables CSS extra directamente en el style del <header>.
|
|
61
|
-
* Útil para pasar tokens del tema: { '--xnav-icon-color': 'var(--accent)' } */
|
|
62
|
-
cssVars?: Record<string, string>;
|
|
63
|
-
/** aria-label del botón hamburguesa cuando está cerrado. Default: "Abrir menú" */
|
|
64
|
-
labelOpen?: string;
|
|
65
|
-
/** aria-label del botón hamburguesa cuando está abierto. Default: "Cerrar menú" */
|
|
66
|
-
labelClose?: string;
|
|
67
|
-
/** Texto del botón de tema oscuro en menú móvil. Default: "Oscuro" */
|
|
68
|
-
labelDark?: string;
|
|
69
|
-
/** Texto del botón de tema claro en menú móvil. Default: "Claro" */
|
|
70
|
-
labelLight?: string;
|
|
71
|
-
/** className extra que se añade al <header> */
|
|
72
|
-
className?: string;
|
|
73
|
-
};
|
|
74
|
-
declare function XNavbar({ linksLeft, linksRight, logo, logoAsThemeToggle, onLogoClick, themeIcons, defaultTheme, storageKey, linkColor, linkHoverColor, linkActiveColor, iconColor, iconHoverColor, iconSize, hamburgerColor, hamburgerBarWidth, hamburgerBarThickness, cssVars, labelOpen, labelClose, labelDark, labelLight, className, }: XNavbarProps): react_jsx_runtime.JSX.Element;
|
|
75
|
-
|
|
76
|
-
export { type IconRenderer, type NavLinkItem, type ThemeToggleIcons, XNavbar, type XNavbarProps };
|
|
1
|
+
export { XNavbar } from "./xnavbar";
|
|
2
|
+
export type { XNavbarProps, NavLinkItem, ThemeToggleIcons, IconRenderer, } from "./xnavbar";
|
|
@@ -41,7 +41,31 @@ var import_link = __toESM(require("next/link"));
|
|
|
41
41
|
var import_navigation = require("next/navigation");
|
|
42
42
|
|
|
43
43
|
// src/components/navigation/xnavbar/XNavbar.module.css
|
|
44
|
-
var XNavbar_default = {
|
|
44
|
+
var XNavbar_default = {
|
|
45
|
+
header: "XNavbar_header3",
|
|
46
|
+
desktopNav: "XNavbar_desktopNav3",
|
|
47
|
+
desktopLinksLeft: "XNavbar_desktopLinksLeft3",
|
|
48
|
+
desktopLinksRight: "XNavbar_desktopLinksRight3",
|
|
49
|
+
logoSlot: "XNavbar_logoSlot3",
|
|
50
|
+
logoWrapper: "XNavbar_logoWrapper3",
|
|
51
|
+
logoBtn: "XNavbar_logoBtn3",
|
|
52
|
+
iconTray: "XNavbar_iconTray3",
|
|
53
|
+
iconTrayRight: "XNavbar_iconTrayRight3",
|
|
54
|
+
iconTrayLeft: "XNavbar_iconTrayLeft3",
|
|
55
|
+
navLink: "XNavbar_navLink3",
|
|
56
|
+
navLinkActive: "XNavbar_navLinkActive3",
|
|
57
|
+
navLinkExternal: "XNavbar_navLinkExternal3",
|
|
58
|
+
mobileToggle: "XNavbar_mobileToggle3",
|
|
59
|
+
hamburgerBtn: "XNavbar_hamburgerBtn3",
|
|
60
|
+
bar: "XNavbar_bar3",
|
|
61
|
+
mobileOverlay: "XNavbar_mobileOverlay3",
|
|
62
|
+
mobileCloseBtn: "XNavbar_mobileCloseBtn3",
|
|
63
|
+
closeBar: "XNavbar_closeBar3",
|
|
64
|
+
mobileLogo: "XNavbar_mobileLogo3",
|
|
65
|
+
mobileNavLink: "XNavbar_mobileNavLink3",
|
|
66
|
+
mobileNavLinkActive: "XNavbar_mobileNavLinkActive3",
|
|
67
|
+
themeToggleMobile: "XNavbar_themeToggleMobile3"
|
|
68
|
+
};
|
|
45
69
|
|
|
46
70
|
// src/components/navigation/xnavbar/XNavbar.tsx
|
|
47
71
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -340,8 +364,4 @@ function XNavbar({
|
|
|
340
364
|
}
|
|
341
365
|
);
|
|
342
366
|
}
|
|
343
|
-
|
|
344
|
-
0 && (module.exports = {
|
|
345
|
-
XNavbar
|
|
346
|
-
});
|
|
347
|
-
//# sourceMappingURL=index.js.map
|
|
367
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/navigation/index.ts","../../../src/components/navigation/xnavbar/XNavbar.tsx","../../../src/components/navigation/xnavbar/XNavbar.module.css"],"sourcesContent":["export { XNavbar } from \"./xnavbar\";\nexport type {\n XNavbarProps,\n NavLinkItem,\n ThemeToggleIcons,\n IconRenderer,\n} from \"./xnavbar\";\n","\"use client\";\n\nimport { useEffect, useState, ReactNode, CSSProperties } from \"react\";\nimport { motion, Variants } from \"framer-motion\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport styles from \"./XNavbar.module.css\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Tipos públicos — exportados para que el consumidor pueda tipear sus datos\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type NavLinkItem = {\n /** Ruta destino */\n url: string;\n /** Texto visible */\n title: string;\n /** Si es true abre en pestaña nueva y muestra el indicador ↗ */\n external?: boolean;\n};\n\n/**\n * ReactNode estático O función de render (size, color?) => ReactNode.\n * La función recibe el tamaño y el color vigente para que el ícono\n * pueda adaptarse dinámicamente a los props del navbar.\n */\nexport type IconRenderer = ReactNode | ((size: number, color?: string) => ReactNode);\n\nexport type ThemeToggleIcons = {\n /** Ícono/renderer hacia tema oscuro (ReactNode o función) */\n toDark: IconRenderer;\n /** Ícono/renderer hacia tema claro (ReactNode o función) */\n toLight: IconRenderer;\n};\n\nexport type XNavbarProps = {\n // ── Navegación ──────────────────────────────────────────────────────────\n /** Links que aparecen a la izquierda del logo en desktop */\n linksLeft?: NavLinkItem[];\n /** Links que aparecen a la derecha del logo en desktop */\n linksRight?: NavLinkItem[];\n\n // ── Logo central ────────────────────────────────────────────────────────\n /** Contenido del botón central (texto o JSX). Por defecto: \"X\" */\n logo?: ReactNode;\n /** Si true el logo actúa como toggle de tema (comportamiento original). Default: true */\n logoAsThemeToggle?: boolean;\n /** Callback custom si logoAsThemeToggle es false */\n onLogoClick?: () => void;\n\n // ── Toggle de tema ──────────────────────────────────────────────────────\n /** Íconos para el toggle de tema. Si no se pasa, no se mostrará hint de ícono */\n themeIcons?: ThemeToggleIcons;\n /** Tema inicial. Default: \"light\" */\n defaultTheme?: \"light\" | \"dark\";\n /** Key de localStorage para persistencia del tema. Default: \"theme\" */\n storageKey?: string;\n\n // ── Color de los enlaces de navegación ──────────────────────────────────────\n /** Color base de los enlaces (Inicio, Contacto, etc.). Default: var(--text) */\n linkColor?: string;\n /** Color al hacer hover sobre los enlaces. Default: opacidad reducida del linkColor */\n linkHoverColor?: string;\n /** Color del borde inferior del enlace activo. Default: linkColor */\n linkActiveColor?: string;\n\n // ── Color y tamaño de íconos theme-toggle ────────────────────────────────\n /** Color base de los íconos. Acepta cualquier valor CSS: hex, hsl, \"var(--accent)\", etc.\n * Si no se pasa, los íconos heredan el color del texto (currentColor). */\n iconColor?: string;\n /** Color que toman los íconos al hacer hover sobre el logo. Default: iconColor */\n iconHoverColor?: string;\n /** Tamaño en px que se pasa a IconRenderer cuando es función. Default: 22 */\n iconSize?: number;\n\n // ── Hamburguesa ──────────────────────────────────────────────────────────\n /** Color de las 3 barras (y la X de cierre móvil). Acepta cualquier valor CSS. Default: var(--text) */\n hamburgerColor?: string;\n /** Ancho de las barras. Cualquier unidad CSS. Default: \"2rem\" */\n hamburgerBarWidth?: string;\n /** Grosor (altura) de las barras. Cualquier unidad CSS. Default: \"3px\" */\n hamburgerBarThickness?: string;\n\n // ── Variables CSS personalizadas ─────────────────────────────────────────\n /** Inyecta variables CSS extra directamente en el style del <header>.\n * Útil para pasar tokens del tema: { '--xnav-icon-color': 'var(--accent)' } */\n cssVars?: Record<string, string>;\n\n // ── Labels de accesibilidad ─────────────────────────────────────────────\n /** aria-label del botón hamburguesa cuando está cerrado. Default: \"Abrir menú\" */\n labelOpen?: string;\n /** aria-label del botón hamburguesa cuando está abierto. Default: \"Cerrar menú\" */\n labelClose?: string;\n /** Texto del botón de tema oscuro en menú móvil. Default: \"Oscuro\" */\n labelDark?: string;\n /** Texto del botón de tema claro en menú móvil. Default: \"Claro\" */\n labelLight?: string;\n\n // ── Estilos adicionales ─────────────────────────────────────────────────\n /** className extra que se añade al <header> */\n className?: string;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Variantes de animación (idénticas al navbar original)\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst iconTrayRightVariants: Variants = {\n hidden: { opacity: 0, x: -6, pointerEvents: \"none\" },\n visible: { opacity: 1, x: 0, pointerEvents: \"none\", transition: { duration: 0.18 } },\n};\nconst iconTrayLeftVariants: Variants = {\n hidden: { opacity: 0, x: 6, pointerEvents: \"none\" },\n visible: { opacity: 1, x: 0, pointerEvents: \"none\", transition: { duration: 0.18 } },\n};\n\nconst topVariants: Variants = { closed: { rotate: 0 }, opened: { rotate: 45 } };\nconst centerVariants: Variants = { closed: { opacity: 1 }, opened: { opacity: 0 } };\nconst bottomVariants: Variants = { closed: { rotate: 0 }, opened: { rotate: -45 } };\n\nconst listVariants: Variants = {\n closed: { x: \"100vw\" },\n opened: { x: 0, transition: { when: \"beforeChildren\", staggerChildren: 0.02 } },\n};\nconst itemVariants: Variants = {\n closed: { x: -10, opacity: 0 },\n opened: { x: 0, opacity: 1 },\n};\n\n/** Renderiza un IconRenderer: si es función la llama con (size, color?), si es ReactNode lo devuelve tal cual. */\nfunction renderIcon(\n icon: IconRenderer,\n size: number,\n color?: string\n): ReactNode {\n if (typeof icon === \"function\") return icon(size, color);\n return icon;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Sub-componente NavLink (interno)\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype NavLinkProps = {\n link: NavLinkItem;\n onClick?: () => void;\n mobile?: boolean;\n};\n\nfunction XNavLink({ link, onClick, mobile }: NavLinkProps) {\n const pathname = usePathname();\n const isActive =\n link.url === \"/\" ? pathname === \"/\" : pathname?.startsWith(link.url);\n\n const baseClass = mobile ? styles.mobileNavLink : styles.navLink;\n const activeClass = mobile ? styles.mobileNavLinkActive : styles.navLinkActive;\n const externalClass = link.external ? styles.navLinkExternal : \"\";\n\n return (\n <Link\n href={link.url}\n onClick={onClick}\n target={link.external ? \"_blank\" : undefined}\n rel={link.external ? \"noopener noreferrer\" : undefined}\n aria-label={`Ir a ${link.title}`}\n aria-current={isActive ? \"page\" : undefined}\n className={[baseClass, isActive ? activeClass : \"\", externalClass]\n .filter(Boolean)\n .join(\" \")}\n >\n {link.title}\n </Link>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Componente principal XNavbar\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport default function XNavbar({\n linksLeft = [],\n linksRight = [],\n logo = \"X\",\n logoAsThemeToggle = true,\n onLogoClick,\n themeIcons,\n defaultTheme = \"light\",\n storageKey = \"theme\",\n linkColor,\n linkHoverColor,\n linkActiveColor,\n iconColor,\n iconHoverColor,\n iconSize = 22,\n hamburgerColor,\n hamburgerBarWidth,\n hamburgerBarThickness,\n cssVars,\n labelOpen = \"Abrir menú\",\n labelClose = \"Cerrar menú\",\n labelDark = \"Oscuro\",\n labelLight = \"Claro\",\n className,\n}: XNavbarProps) {\n const [open, setOpen] = useState(false);\n const [hoverX, setHoverX] = useState(false);\n const [theme, setTheme] = useState<\"light\" | \"dark\">(defaultTheme);\n\n // Persistir tema\n useEffect(() => {\n const saved = (typeof window !== \"undefined\" &&\n localStorage.getItem(storageKey)) as \"light\" | \"dark\" | null;\n applyTheme(saved ?? defaultTheme);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n function applyTheme(t: \"light\" | \"dark\") {\n setTheme(t);\n const root = document.documentElement;\n if (t === \"dark\") root.setAttribute(\"data-theme\", \"dark\");\n else root.removeAttribute(\"data-theme\");\n localStorage.setItem(storageKey, t);\n }\n\n function toggleTheme() {\n applyTheme(theme === \"dark\" ? \"light\" : \"dark\");\n }\n\n // Bloquear scroll — usamos documentElement para no tocar document.body\n useEffect(() => {\n document.documentElement.style.overflow = open ? \"hidden\" : \"\";\n return () => { document.documentElement.style.overflow = \"\"; };\n }, [open]);\n\n // Cerrar con ESC\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open]);\n\n const allLinks = [...linksLeft, ...linksRight];\n\n // ── CSS vars inyectadas en el <header> via inline style ─────────────────\n // Usando \"--xnav-*\" como namespace para no colisionar con vars globales.\n const headerStyle = {\n ...(linkColor && { \"--xnav-link-color\" : linkColor }),\n ...(linkHoverColor && { \"--xnav-link-hover\" : linkHoverColor }),\n ...(linkActiveColor && { \"--xnav-link-active\" : linkActiveColor }),\n ...(iconColor && { \"--xnav-icon-color\" : iconColor }),\n ...(iconHoverColor && { \"--xnav-icon-hover\" : iconHoverColor }),\n ...(hamburgerColor && { \"--xnav-bar-color\" : hamburgerColor }),\n ...(hamburgerBarWidth && { \"--xnav-bar-w\" : hamburgerBarWidth }),\n ...(hamburgerBarThickness && { \"--xnav-bar-h\" : hamburgerBarThickness }),\n ...cssVars,\n } as CSSProperties;\n\n // Acción del logo central\n const handleLogoClick = () => {\n if (logoAsThemeToggle) {\n toggleTheme();\n } else {\n onLogoClick?.();\n }\n };\n\n const logoAriaLabel = logoAsThemeToggle\n ? `Cambiar a tema ${theme === \"dark\" ? \"claro\" : \"oscuro\"}`\n : undefined;\n\n const logoTitle = logoAsThemeToggle\n ? theme === \"dark\"\n ? \"Cambiar a tema claro\"\n : \"Cambiar a tema oscuro\"\n : undefined;\n\n return (\n <header\n className={[styles.header, className].filter(Boolean).join(\" \")}\n style={headerStyle}\n role=\"banner\"\n >\n {/* ── Desktop ── */}\n <nav className={styles.desktopNav} aria-label=\"Navegación principal\">\n <div className={styles.desktopLinksLeft}>\n {linksLeft.map((link) => (\n <XNavLink key={link.url + link.title} link={link} />\n ))}\n </div>\n\n {/* Botón logo central */}\n <div className={styles.logoSlot}>\n <div\n className={styles.logoWrapper}\n onMouseEnter={() => setHoverX(true)}\n onMouseLeave={() => setHoverX(false)}\n >\n <button\n type=\"button\"\n onClick={handleLogoClick}\n aria-label={logoAriaLabel}\n title={logoTitle}\n className={styles.logoBtn}\n >\n {logo}\n </button>\n\n {/* Ícono hint al hover (solo si se pasan themeIcons y el logo es toggle de tema) */}\n {logoAsThemeToggle && themeIcons && (\n <>\n {theme === \"light\" ? (\n <motion.div\n initial={false}\n animate={hoverX ? \"visible\" : \"hidden\"}\n variants={iconTrayRightVariants}\n className={`${styles.iconTray} ${styles.iconTrayRight}`}\n style={{\n color:\n (hoverX ? iconHoverColor ?? iconColor : iconColor) ||\n undefined,\n }}\n aria-hidden\n >\n {renderIcon(themeIcons.toDark, iconSize, iconColor)}\n </motion.div>\n ) : (\n <motion.div\n initial={false}\n animate={hoverX ? \"visible\" : \"hidden\"}\n variants={iconTrayLeftVariants}\n className={`${styles.iconTray} ${styles.iconTrayLeft}`}\n style={{\n color:\n (hoverX ? iconHoverColor ?? iconColor : iconColor) ||\n undefined,\n }}\n aria-hidden\n >\n {renderIcon(themeIcons.toLight, iconSize, iconColor)}\n </motion.div>\n )}\n </>\n )}\n </div>\n </div>\n\n <div className={styles.desktopLinksRight}>\n {linksRight.map((link) => (\n <XNavLink key={link.url + link.title} link={link} />\n ))}\n </div>\n </nav>\n\n {/* ── Mobile: botón hamburguesa ── */}\n <div className={styles.mobileToggle}>\n <button\n aria-label={open ? labelClose : labelOpen}\n aria-expanded={open}\n aria-controls=\"xnavbar-mobile-menu\"\n onClick={() => setOpen((p) => !p)}\n className={styles.hamburgerBtn}\n title={open ? labelClose : labelOpen}\n >\n <motion.div\n variants={topVariants}\n initial=\"closed\"\n animate={open ? \"opened\" : \"closed\"}\n className={styles.bar}\n style={{ originX: \"left\" }}\n aria-hidden\n />\n <motion.div\n variants={centerVariants}\n initial=\"closed\"\n animate={open ? \"opened\" : \"closed\"}\n className={styles.bar}\n aria-hidden\n />\n <motion.div\n variants={bottomVariants}\n initial=\"closed\"\n animate={open ? \"opened\" : \"closed\"}\n className={styles.bar}\n style={{ originX: \"left\" }}\n aria-hidden\n />\n </button>\n </div>\n\n {/* ── Mobile overlay — position:fixed, sin portal, sin document.body ── */}\n {open && (\n <motion.div\n id=\"xnavbar-mobile-menu\"\n variants={listVariants}\n initial=\"closed\"\n animate=\"opened\"\n className={styles.mobileOverlay}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Menú de navegación\"\n >\n {/* Botón cerrar */}\n <button\n aria-label={labelClose}\n onClick={() => setOpen(false)}\n className={styles.mobileCloseBtn}\n style={{ WebkitTapHighlightColor: \"transparent\" }}\n >\n <span\n aria-hidden\n className={styles.closeBar}\n style={{ transform: \"rotate(45deg)\" }}\n />\n <span\n aria-hidden\n className={styles.closeBar}\n style={{ transform: \"rotate(-45deg)\" }}\n />\n <span className=\"sr-only\">{labelClose}</span>\n </button>\n\n {/* Logo decorativo */}\n <motion.div variants={itemVariants} className={styles.mobileLogo}>\n {logo}\n </motion.div>\n\n {/* Links */}\n {allLinks.map((link) => (\n <motion.div key={link.url + link.title} variants={itemVariants}>\n <XNavLink\n link={link}\n onClick={() => setOpen(false)}\n mobile\n />\n </motion.div>\n ))}\n\n {/* Toggle de tema */}\n <motion.button\n variants={itemVariants}\n onClick={toggleTheme}\n className={styles.themeToggleMobile}\n >\n {themeIcons ? (\n theme === \"light\" ? (\n <>\n {renderIcon(themeIcons.toDark, iconSize, iconColor)}\n {labelDark}\n </>\n ) : (\n <>\n {renderIcon(themeIcons.toLight, iconSize, iconColor)}\n {labelLight}\n </>\n )\n ) : theme === \"light\" ? (\n labelDark\n ) : (\n labelLight\n )}\n </motion.button>\n </motion.div>\n )}\n </header>\n );\n}\n","/* ────────────────────────────────────────────\n XNavbar.module.css\n Navbar completamente libre de Tailwind.\n Usa variables CSS del tema global (--bg, --text, --border, --accent).\n ──────────────────────────────────────────── */\n\n/* ── Header / contenedor raíz ── */\n.header {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2rem 3rem;\n background: var(--bg);\n color: var(--text);\n font-size: 1.25rem;\n z-index: 60;\n}\n\n@media (min-width: 640px) { .header { padding-inline: 2rem; } }\n@media (min-width: 768px) { .header { padding-inline: 3rem; } }\n@media (min-width: 1024px) { .header { padding-inline: 5rem; } }\n@media (min-width: 1280px) { .header { padding-inline: 12rem; } }\n\n/* ── Desktop nav ── */\n.desktopNav {\n display: none;\n align-items: center;\n width: 100%;\n grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\n padding-bottom: 0.5rem;\n}\n\n@media (min-width: 768px) {\n .desktopNav {\n display: grid;\n }\n}\n\n.desktopLinksLeft,\n.desktopLinksRight {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n min-width: 0;\n}\n\n.desktopLinksLeft {\n justify-content: flex-end;\n}\n\n.desktopLinksRight {\n justify-content: flex-start;\n}\n\n.logoSlot {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* ── Logo / botón central (desktop) ── */\n.logoWrapper {\n position: relative;\n margin-inline: 1rem;\n display: flex;\n align-items: center;\n}\n\n.logoBtn {\n font-weight: 700;\n font-size: 1.5rem;\n line-height: 1;\n user-select: none;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text);\n padding: 0;\n}\n\n/* ── Tray de íconos hover (sun/moon) ── */\n.iconTray {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n.iconTrayRight {\n left: 100%;\n padding-left: 0.75rem;\n}\n\n.iconTrayLeft {\n right: 100%;\n padding-right: 0.75rem;\n}\n\n/* ── NavLink (desktop) ── */\n.navLink {\n padding: 0.25rem;\n border-bottom: 2px solid transparent;\n transition: border-color 0.2s, opacity 0.2s, color 0.2s;\n color: var(--xnav-link-color, var(--text));\n text-decoration: none;\n white-space: nowrap;\n}\n\n.navLink:hover {\n color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));\n opacity: var(--xnav-link-hover-opacity, 0.7);\n}\n\n.navLinkActive {\n border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));\n font-weight: 600;\n}\n\n/* External link indicator */\n.navLinkExternal::after {\n content: \" ↗\";\n font-size: 0.7em;\n opacity: 0.6;\n}\n\n/* ── Mobile hamburger ── */\n.mobileToggle {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n@media (min-width: 768px) {\n .mobileToggle {\n display: none;\n }\n}\n\n.hamburgerBtn {\n width: 2.5rem;\n height: 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: space-between;\n background: none;\n border: none;\n cursor: pointer;\n position: relative;\n z-index: 80;\n padding: 0;\n}\n\n.bar {\n width: var(--xnav-bar-w, 2rem);\n height: var(--xnav-bar-h, 3px);\n background: var(--xnav-bar-color, var(--text));\n border-radius: 2px;\n}\n\n/* ── Mobile overlay (portal) ── */\n.mobileOverlay {\n position: fixed;\n inset: 0;\n width: 100vw;\n height: 100svh;\n background: var(--bg);\n color: var(--text);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2rem;\n font-size: 2.5rem;\n z-index: 9999;\n}\n\n.mobileCloseBtn {\n position: fixed;\n top: 2rem;\n left: 1rem;\n width: 2.5rem;\n height: 2rem;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n /* hereda el mismo color que las barras del hamburguesa */\n color: var(--xnav-bar-color, var(--text));\n z-index: 10000;\n -webkit-tap-highlight-color: transparent;\n}\n\n.closeBar {\n display: block;\n position: absolute;\n width: 2rem;\n height: 3px;\n border-radius: 2px;\n background: currentColor;\n}\n\n.mobileLogo {\n font-weight: 700;\n font-size: 3rem;\n user-select: none;\n pointer-events: none;\n}\n\n.mobileNavLink {\n font-size: 2.5rem;\n color: var(--xnav-link-color, var(--text));\n text-decoration: none;\n border-bottom: 2px solid transparent;\n transition: border-color 0.2s, color 0.2s, opacity 0.2s;\n padding: 0.25rem;\n}\n\n.mobileNavLink:hover {\n color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));\n opacity: var(--xnav-link-hover-opacity, 0.7);\n}\n\n.mobileNavLinkActive {\n font-weight: 600;\n border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));\n}\n\n/* ── Botón tema (móvil) ── */\n.themeToggleMobile {\n margin-top: 1rem;\n font-size: 1rem;\n padding: 0.5rem 1rem;\n border: 1px solid var(--border);\n border-radius: 0.375rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: none;\n color: var(--text);\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n.themeToggleMobile:hover {\n opacity: 0.7;\n}\n"],"mappings":"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","names":["Link"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/components/navigation/index.ts", "../../../src/components/navigation/xnavbar/XNavbar.tsx", "../../../src/components/navigation/xnavbar/XNavbar.module.css"],
|
|
4
|
+
"sourcesContent": ["export { XNavbar } from \"./xnavbar\";\nexport type {\n XNavbarProps,\n NavLinkItem,\n ThemeToggleIcons,\n IconRenderer,\n} from \"./xnavbar\";\n", "\"use client\";\n\nimport { useEffect, useState, ReactNode, CSSProperties } from \"react\";\nimport { motion, Variants } from \"framer-motion\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport styles from \"./XNavbar.module.css\";\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Tipos p\u00FAblicos \u2014 exportados para que el consumidor pueda tipear sus datos\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type NavLinkItem = {\n /** Ruta destino */\n url: string;\n /** Texto visible */\n title: string;\n /** Si es true abre en pesta\u00F1a nueva y muestra el indicador \u2197 */\n external?: boolean;\n};\n\n/**\n * ReactNode est\u00E1tico O funci\u00F3n de render (size, color?) => ReactNode.\n * La funci\u00F3n recibe el tama\u00F1o y el color vigente para que el \u00EDcono\n * pueda adaptarse din\u00E1micamente a los props del navbar.\n */\nexport type IconRenderer = ReactNode | ((size: number, color?: string) => ReactNode);\n\nexport type ThemeToggleIcons = {\n /** \u00CDcono/renderer hacia tema oscuro (ReactNode o funci\u00F3n) */\n toDark: IconRenderer;\n /** \u00CDcono/renderer hacia tema claro (ReactNode o funci\u00F3n) */\n toLight: IconRenderer;\n};\n\nexport type XNavbarProps = {\n // \u2500\u2500 Navegaci\u00F3n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Links que aparecen a la izquierda del logo en desktop */\n linksLeft?: NavLinkItem[];\n /** Links que aparecen a la derecha del logo en desktop */\n linksRight?: NavLinkItem[];\n\n // \u2500\u2500 Logo central \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Contenido del bot\u00F3n central (texto o JSX). Por defecto: \"X\" */\n logo?: ReactNode;\n /** Si true el logo act\u00FAa como toggle de tema (comportamiento original). Default: true */\n logoAsThemeToggle?: boolean;\n /** Callback custom si logoAsThemeToggle es false */\n onLogoClick?: () => void;\n\n // \u2500\u2500 Toggle de tema \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** \u00CDconos para el toggle de tema. Si no se pasa, no se mostrar\u00E1 hint de \u00EDcono */\n themeIcons?: ThemeToggleIcons;\n /** Tema inicial. Default: \"light\" */\n defaultTheme?: \"light\" | \"dark\";\n /** Key de localStorage para persistencia del tema. Default: \"theme\" */\n storageKey?: string;\n\n // \u2500\u2500 Color de los enlaces de navegaci\u00F3n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Color base de los enlaces (Inicio, Contacto, etc.). Default: var(--text) */\n linkColor?: string;\n /** Color al hacer hover sobre los enlaces. Default: opacidad reducida del linkColor */\n linkHoverColor?: string;\n /** Color del borde inferior del enlace activo. Default: linkColor */\n linkActiveColor?: string;\n\n // \u2500\u2500 Color y tama\u00F1o de \u00EDconos theme-toggle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Color base de los \u00EDconos. Acepta cualquier valor CSS: hex, hsl, \"var(--accent)\", etc.\n * Si no se pasa, los \u00EDconos heredan el color del texto (currentColor). */\n iconColor?: string;\n /** Color que toman los \u00EDconos al hacer hover sobre el logo. Default: iconColor */\n iconHoverColor?: string;\n /** Tama\u00F1o en px que se pasa a IconRenderer cuando es funci\u00F3n. Default: 22 */\n iconSize?: number;\n\n // \u2500\u2500 Hamburguesa \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Color de las 3 barras (y la X de cierre m\u00F3vil). Acepta cualquier valor CSS. Default: var(--text) */\n hamburgerColor?: string;\n /** Ancho de las barras. Cualquier unidad CSS. Default: \"2rem\" */\n hamburgerBarWidth?: string;\n /** Grosor (altura) de las barras. Cualquier unidad CSS. Default: \"3px\" */\n hamburgerBarThickness?: string;\n\n // \u2500\u2500 Variables CSS personalizadas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Inyecta variables CSS extra directamente en el style del <header>.\n * \u00DAtil para pasar tokens del tema: { '--xnav-icon-color': 'var(--accent)' } */\n cssVars?: Record<string, string>;\n\n // \u2500\u2500 Labels de accesibilidad \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** aria-label del bot\u00F3n hamburguesa cuando est\u00E1 cerrado. Default: \"Abrir men\u00FA\" */\n labelOpen?: string;\n /** aria-label del bot\u00F3n hamburguesa cuando est\u00E1 abierto. Default: \"Cerrar men\u00FA\" */\n labelClose?: string;\n /** Texto del bot\u00F3n de tema oscuro en men\u00FA m\u00F3vil. Default: \"Oscuro\" */\n labelDark?: string;\n /** Texto del bot\u00F3n de tema claro en men\u00FA m\u00F3vil. Default: \"Claro\" */\n labelLight?: string;\n\n // \u2500\u2500 Estilos adicionales \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** className extra que se a\u00F1ade al <header> */\n className?: string;\n};\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Variantes de animaci\u00F3n (id\u00E9nticas al navbar original)\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst iconTrayRightVariants: Variants = {\n hidden: { opacity: 0, x: -6, pointerEvents: \"none\" },\n visible: { opacity: 1, x: 0, pointerEvents: \"none\", transition: { duration: 0.18 } },\n};\nconst iconTrayLeftVariants: Variants = {\n hidden: { opacity: 0, x: 6, pointerEvents: \"none\" },\n visible: { opacity: 1, x: 0, pointerEvents: \"none\", transition: { duration: 0.18 } },\n};\n\nconst topVariants: Variants = { closed: { rotate: 0 }, opened: { rotate: 45 } };\nconst centerVariants: Variants = { closed: { opacity: 1 }, opened: { opacity: 0 } };\nconst bottomVariants: Variants = { closed: { rotate: 0 }, opened: { rotate: -45 } };\n\nconst listVariants: Variants = {\n closed: { x: \"100vw\" },\n opened: { x: 0, transition: { when: \"beforeChildren\", staggerChildren: 0.02 } },\n};\nconst itemVariants: Variants = {\n closed: { x: -10, opacity: 0 },\n opened: { x: 0, opacity: 1 },\n};\n\n/** Renderiza un IconRenderer: si es funci\u00F3n la llama con (size, color?), si es ReactNode lo devuelve tal cual. */\nfunction renderIcon(\n icon: IconRenderer,\n size: number,\n color?: string\n): ReactNode {\n if (typeof icon === \"function\") return icon(size, color);\n return icon;\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Sub-componente NavLink (interno)\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype NavLinkProps = {\n link: NavLinkItem;\n onClick?: () => void;\n mobile?: boolean;\n};\n\nfunction XNavLink({ link, onClick, mobile }: NavLinkProps) {\n const pathname = usePathname();\n const isActive =\n link.url === \"/\" ? pathname === \"/\" : pathname?.startsWith(link.url);\n\n const baseClass = mobile ? styles.mobileNavLink : styles.navLink;\n const activeClass = mobile ? styles.mobileNavLinkActive : styles.navLinkActive;\n const externalClass = link.external ? styles.navLinkExternal : \"\";\n\n return (\n <Link\n href={link.url}\n onClick={onClick}\n target={link.external ? \"_blank\" : undefined}\n rel={link.external ? \"noopener noreferrer\" : undefined}\n aria-label={`Ir a ${link.title}`}\n aria-current={isActive ? \"page\" : undefined}\n className={[baseClass, isActive ? activeClass : \"\", externalClass]\n .filter(Boolean)\n .join(\" \")}\n >\n {link.title}\n </Link>\n );\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Componente principal XNavbar\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function XNavbar({\n linksLeft = [],\n linksRight = [],\n logo = \"X\",\n logoAsThemeToggle = true,\n onLogoClick,\n themeIcons,\n defaultTheme = \"light\",\n storageKey = \"theme\",\n linkColor,\n linkHoverColor,\n linkActiveColor,\n iconColor,\n iconHoverColor,\n iconSize = 22,\n hamburgerColor,\n hamburgerBarWidth,\n hamburgerBarThickness,\n cssVars,\n labelOpen = \"Abrir men\u00FA\",\n labelClose = \"Cerrar men\u00FA\",\n labelDark = \"Oscuro\",\n labelLight = \"Claro\",\n className,\n}: XNavbarProps) {\n const [open, setOpen] = useState(false);\n const [hoverX, setHoverX] = useState(false);\n const [theme, setTheme] = useState<\"light\" | \"dark\">(defaultTheme);\n\n // Persistir tema\n useEffect(() => {\n const saved = (typeof window !== \"undefined\" &&\n localStorage.getItem(storageKey)) as \"light\" | \"dark\" | null;\n applyTheme(saved ?? defaultTheme);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n function applyTheme(t: \"light\" | \"dark\") {\n setTheme(t);\n const root = document.documentElement;\n if (t === \"dark\") root.setAttribute(\"data-theme\", \"dark\");\n else root.removeAttribute(\"data-theme\");\n localStorage.setItem(storageKey, t);\n }\n\n function toggleTheme() {\n applyTheme(theme === \"dark\" ? \"light\" : \"dark\");\n }\n\n // Bloquear scroll \u2014 usamos documentElement para no tocar document.body\n useEffect(() => {\n document.documentElement.style.overflow = open ? \"hidden\" : \"\";\n return () => { document.documentElement.style.overflow = \"\"; };\n }, [open]);\n\n // Cerrar con ESC\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open]);\n\n const allLinks = [...linksLeft, ...linksRight];\n\n // \u2500\u2500 CSS vars inyectadas en el <header> via inline style \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Usando \"--xnav-*\" como namespace para no colisionar con vars globales.\n const headerStyle = {\n ...(linkColor && { \"--xnav-link-color\" : linkColor }),\n ...(linkHoverColor && { \"--xnav-link-hover\" : linkHoverColor }),\n ...(linkActiveColor && { \"--xnav-link-active\" : linkActiveColor }),\n ...(iconColor && { \"--xnav-icon-color\" : iconColor }),\n ...(iconHoverColor && { \"--xnav-icon-hover\" : iconHoverColor }),\n ...(hamburgerColor && { \"--xnav-bar-color\" : hamburgerColor }),\n ...(hamburgerBarWidth && { \"--xnav-bar-w\" : hamburgerBarWidth }),\n ...(hamburgerBarThickness && { \"--xnav-bar-h\" : hamburgerBarThickness }),\n ...cssVars,\n } as CSSProperties;\n\n // Acci\u00F3n del logo central\n const handleLogoClick = () => {\n if (logoAsThemeToggle) {\n toggleTheme();\n } else {\n onLogoClick?.();\n }\n };\n\n const logoAriaLabel = logoAsThemeToggle\n ? `Cambiar a tema ${theme === \"dark\" ? \"claro\" : \"oscuro\"}`\n : undefined;\n\n const logoTitle = logoAsThemeToggle\n ? theme === \"dark\"\n ? \"Cambiar a tema claro\"\n : \"Cambiar a tema oscuro\"\n : undefined;\n\n return (\n <header\n className={[styles.header, className].filter(Boolean).join(\" \")}\n style={headerStyle}\n role=\"banner\"\n >\n {/* \u2500\u2500 Desktop \u2500\u2500 */}\n <nav className={styles.desktopNav} aria-label=\"Navegaci\u00F3n principal\">\n <div className={styles.desktopLinksLeft}>\n {linksLeft.map((link) => (\n <XNavLink key={link.url + link.title} link={link} />\n ))}\n </div>\n\n {/* Bot\u00F3n logo central */}\n <div className={styles.logoSlot}>\n <div\n className={styles.logoWrapper}\n onMouseEnter={() => setHoverX(true)}\n onMouseLeave={() => setHoverX(false)}\n >\n <button\n type=\"button\"\n onClick={handleLogoClick}\n aria-label={logoAriaLabel}\n title={logoTitle}\n className={styles.logoBtn}\n >\n {logo}\n </button>\n\n {/* \u00CDcono hint al hover (solo si se pasan themeIcons y el logo es toggle de tema) */}\n {logoAsThemeToggle && themeIcons && (\n <>\n {theme === \"light\" ? (\n <motion.div\n initial={false}\n animate={hoverX ? \"visible\" : \"hidden\"}\n variants={iconTrayRightVariants}\n className={`${styles.iconTray} ${styles.iconTrayRight}`}\n style={{\n color:\n (hoverX ? iconHoverColor ?? iconColor : iconColor) ||\n undefined,\n }}\n aria-hidden\n >\n {renderIcon(themeIcons.toDark, iconSize, iconColor)}\n </motion.div>\n ) : (\n <motion.div\n initial={false}\n animate={hoverX ? \"visible\" : \"hidden\"}\n variants={iconTrayLeftVariants}\n className={`${styles.iconTray} ${styles.iconTrayLeft}`}\n style={{\n color:\n (hoverX ? iconHoverColor ?? iconColor : iconColor) ||\n undefined,\n }}\n aria-hidden\n >\n {renderIcon(themeIcons.toLight, iconSize, iconColor)}\n </motion.div>\n )}\n </>\n )}\n </div>\n </div>\n\n <div className={styles.desktopLinksRight}>\n {linksRight.map((link) => (\n <XNavLink key={link.url + link.title} link={link} />\n ))}\n </div>\n </nav>\n\n {/* \u2500\u2500 Mobile: bot\u00F3n hamburguesa \u2500\u2500 */}\n <div className={styles.mobileToggle}>\n <button\n aria-label={open ? labelClose : labelOpen}\n aria-expanded={open}\n aria-controls=\"xnavbar-mobile-menu\"\n onClick={() => setOpen((p) => !p)}\n className={styles.hamburgerBtn}\n title={open ? labelClose : labelOpen}\n >\n <motion.div\n variants={topVariants}\n initial=\"closed\"\n animate={open ? \"opened\" : \"closed\"}\n className={styles.bar}\n style={{ originX: \"left\" }}\n aria-hidden\n />\n <motion.div\n variants={centerVariants}\n initial=\"closed\"\n animate={open ? \"opened\" : \"closed\"}\n className={styles.bar}\n aria-hidden\n />\n <motion.div\n variants={bottomVariants}\n initial=\"closed\"\n animate={open ? \"opened\" : \"closed\"}\n className={styles.bar}\n style={{ originX: \"left\" }}\n aria-hidden\n />\n </button>\n </div>\n\n {/* \u2500\u2500 Mobile overlay \u2014 position:fixed, sin portal, sin document.body \u2500\u2500 */}\n {open && (\n <motion.div\n id=\"xnavbar-mobile-menu\"\n variants={listVariants}\n initial=\"closed\"\n animate=\"opened\"\n className={styles.mobileOverlay}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Men\u00FA de navegaci\u00F3n\"\n >\n {/* Bot\u00F3n cerrar */}\n <button\n aria-label={labelClose}\n onClick={() => setOpen(false)}\n className={styles.mobileCloseBtn}\n style={{ WebkitTapHighlightColor: \"transparent\" }}\n >\n <span\n aria-hidden\n className={styles.closeBar}\n style={{ transform: \"rotate(45deg)\" }}\n />\n <span\n aria-hidden\n className={styles.closeBar}\n style={{ transform: \"rotate(-45deg)\" }}\n />\n <span className=\"sr-only\">{labelClose}</span>\n </button>\n\n {/* Logo decorativo */}\n <motion.div variants={itemVariants} className={styles.mobileLogo}>\n {logo}\n </motion.div>\n\n {/* Links */}\n {allLinks.map((link) => (\n <motion.div key={link.url + link.title} variants={itemVariants}>\n <XNavLink\n link={link}\n onClick={() => setOpen(false)}\n mobile\n />\n </motion.div>\n ))}\n\n {/* Toggle de tema */}\n <motion.button\n variants={itemVariants}\n onClick={toggleTheme}\n className={styles.themeToggleMobile}\n >\n {themeIcons ? (\n theme === \"light\" ? (\n <>\n {renderIcon(themeIcons.toDark, iconSize, iconColor)}\n {labelDark}\n </>\n ) : (\n <>\n {renderIcon(themeIcons.toLight, iconSize, iconColor)}\n {labelLight}\n </>\n )\n ) : theme === \"light\" ? (\n labelDark\n ) : (\n labelLight\n )}\n </motion.button>\n </motion.div>\n )}\n </header>\n );\n}\n", "/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n XNavbar.module.css\n Navbar completamente libre de Tailwind.\n Usa variables CSS del tema global (--bg, --text, --border, --accent).\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* \u2500\u2500 Header / contenedor ra\u00EDz \u2500\u2500 */\n.header {\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2rem 3rem;\n background: var(--bg);\n color: var(--text);\n font-size: 1.25rem;\n z-index: 60;\n}\n\n@media (min-width: 640px) { .header { padding-inline: 2rem; } }\n@media (min-width: 768px) { .header { padding-inline: 3rem; } }\n@media (min-width: 1024px) { .header { padding-inline: 5rem; } }\n@media (min-width: 1280px) { .header { padding-inline: 12rem; } }\n\n/* \u2500\u2500 Desktop nav \u2500\u2500 */\n.desktopNav {\n display: none;\n align-items: center;\n width: 100%;\n grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\n padding-bottom: 0.5rem;\n}\n\n@media (min-width: 768px) {\n .desktopNav {\n display: grid;\n }\n}\n\n.desktopLinksLeft,\n.desktopLinksRight {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n min-width: 0;\n}\n\n.desktopLinksLeft {\n justify-content: flex-end;\n}\n\n.desktopLinksRight {\n justify-content: flex-start;\n}\n\n.logoSlot {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* \u2500\u2500 Logo / bot\u00F3n central (desktop) \u2500\u2500 */\n.logoWrapper {\n position: relative;\n margin-inline: 1rem;\n display: flex;\n align-items: center;\n}\n\n.logoBtn {\n font-weight: 700;\n font-size: 1.5rem;\n line-height: 1;\n user-select: none;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text);\n padding: 0;\n}\n\n/* \u2500\u2500 Tray de \u00EDconos hover (sun/moon) \u2500\u2500 */\n.iconTray {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n.iconTrayRight {\n left: 100%;\n padding-left: 0.75rem;\n}\n\n.iconTrayLeft {\n right: 100%;\n padding-right: 0.75rem;\n}\n\n/* \u2500\u2500 NavLink (desktop) \u2500\u2500 */\n.navLink {\n padding: 0.25rem;\n border-bottom: 2px solid transparent;\n transition: border-color 0.2s, opacity 0.2s, color 0.2s;\n color: var(--xnav-link-color, var(--text));\n text-decoration: none;\n white-space: nowrap;\n}\n\n.navLink:hover {\n color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));\n opacity: var(--xnav-link-hover-opacity, 0.7);\n}\n\n.navLinkActive {\n border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));\n font-weight: 600;\n}\n\n/* External link indicator */\n.navLinkExternal::after {\n content: \" \u2197\";\n font-size: 0.7em;\n opacity: 0.6;\n}\n\n/* \u2500\u2500 Mobile hamburger \u2500\u2500 */\n.mobileToggle {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n@media (min-width: 768px) {\n .mobileToggle {\n display: none;\n }\n}\n\n.hamburgerBtn {\n width: 2.5rem;\n height: 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: space-between;\n background: none;\n border: none;\n cursor: pointer;\n position: relative;\n z-index: 80;\n padding: 0;\n}\n\n.bar {\n width: var(--xnav-bar-w, 2rem);\n height: var(--xnav-bar-h, 3px);\n background: var(--xnav-bar-color, var(--text));\n border-radius: 2px;\n}\n\n/* \u2500\u2500 Mobile overlay (portal) \u2500\u2500 */\n.mobileOverlay {\n position: fixed;\n inset: 0;\n width: 100vw;\n height: 100svh;\n background: var(--bg);\n color: var(--text);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2rem;\n font-size: 2.5rem;\n z-index: 9999;\n}\n\n.mobileCloseBtn {\n position: fixed;\n top: 2rem;\n left: 1rem;\n width: 2.5rem;\n height: 2rem;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n /* hereda el mismo color que las barras del hamburguesa */\n color: var(--xnav-bar-color, var(--text));\n z-index: 10000;\n -webkit-tap-highlight-color: transparent;\n}\n\n.closeBar {\n display: block;\n position: absolute;\n width: 2rem;\n height: 3px;\n border-radius: 2px;\n background: currentColor;\n}\n\n.mobileLogo {\n font-weight: 700;\n font-size: 3rem;\n user-select: none;\n pointer-events: none;\n}\n\n.mobileNavLink {\n font-size: 2.5rem;\n color: var(--xnav-link-color, var(--text));\n text-decoration: none;\n border-bottom: 2px solid transparent;\n transition: border-color 0.2s, color 0.2s, opacity 0.2s;\n padding: 0.25rem;\n}\n\n.mobileNavLink:hover {\n color: var(--xnav-link-hover, var(--xnav-link-color, var(--text)));\n opacity: var(--xnav-link-hover-opacity, 0.7);\n}\n\n.mobileNavLinkActive {\n font-weight: 600;\n border-bottom-color: var(--xnav-link-active, var(--xnav-link-color, var(--text)));\n}\n\n/* \u2500\u2500 Bot\u00F3n tema (m\u00F3vil) \u2500\u2500 */\n.themeToggleMobile {\n margin-top: 1rem;\n font-size: 1rem;\n padding: 0.5rem 1rem;\n border: 1px solid var(--border);\n border-radius: 0.375rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: none;\n color: var(--text);\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n.themeToggleMobile:hover {\n opacity: 0.7;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["header", "desktopNav", "desktopLinksLeft", "desktopLinksRight", "logoSlot", "logoWrapper", "logoBtn", "iconTray", "iconTrayRight", "iconTrayLeft", "navLink", "navLinkActive", "navLinkExternal", "mobileToggle", "hamburgerBtn", "bar", "mobileOverlay", "mobileCloseBtn", "closeBar", "mobileLogo", "mobileNavLink", "mobileNavLinkActive", "themeToggleMobile", "Link"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type NavLinkItem = {
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
export type NavLinkItem = {
|
|
5
3
|
/** Ruta destino */
|
|
6
4
|
url: string;
|
|
7
5
|
/** Texto visible */
|
|
@@ -14,14 +12,14 @@ type NavLinkItem = {
|
|
|
14
12
|
* La función recibe el tamaño y el color vigente para que el ícono
|
|
15
13
|
* pueda adaptarse dinámicamente a los props del navbar.
|
|
16
14
|
*/
|
|
17
|
-
type IconRenderer = ReactNode | ((size: number, color?: string) => ReactNode);
|
|
18
|
-
type ThemeToggleIcons = {
|
|
15
|
+
export type IconRenderer = ReactNode | ((size: number, color?: string) => ReactNode);
|
|
16
|
+
export type ThemeToggleIcons = {
|
|
19
17
|
/** Ícono/renderer hacia tema oscuro (ReactNode o función) */
|
|
20
18
|
toDark: IconRenderer;
|
|
21
19
|
/** Ícono/renderer hacia tema claro (ReactNode o función) */
|
|
22
20
|
toLight: IconRenderer;
|
|
23
21
|
};
|
|
24
|
-
type XNavbarProps = {
|
|
22
|
+
export type XNavbarProps = {
|
|
25
23
|
/** Links que aparecen a la izquierda del logo en desktop */
|
|
26
24
|
linksLeft?: NavLinkItem[];
|
|
27
25
|
/** Links que aparecen a la derecha del logo en desktop */
|
|
@@ -71,6 +69,4 @@ type XNavbarProps = {
|
|
|
71
69
|
/** className extra que se añade al <header> */
|
|
72
70
|
className?: string;
|
|
73
71
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export { type IconRenderer, type NavLinkItem, type ThemeToggleIcons, XNavbar, type XNavbarProps };
|
|
72
|
+
export default function XNavbar({ linksLeft, linksRight, logo, logoAsThemeToggle, onLogoClick, themeIcons, defaultTheme, storageKey, linkColor, linkHoverColor, linkActiveColor, iconColor, iconHoverColor, iconSize, hamburgerColor, hamburgerBarWidth, hamburgerBarThickness, cssVars, labelOpen, labelClose, labelDark, labelLight, className, }: XNavbarProps): import("react/jsx-runtime").JSX.Element;
|