@xscriptor/xcomponents 0.1.0
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/CODE_OF_CONDUCT.md +35 -0
- package/CONTRIBUTING.md +64 -0
- package/LICENSE +21 -0
- package/README.md +127 -0
- package/SECURITY.md +25 -0
- package/dist/chunk-2OAXRRVQ.mjs +150 -0
- package/dist/chunk-2OAXRRVQ.mjs.map +1 -0
- package/dist/chunk-42XPBYTL.mjs +186 -0
- package/dist/chunk-42XPBYTL.mjs.map +1 -0
- package/dist/chunk-5G4P2E76.mjs +66 -0
- package/dist/chunk-5G4P2E76.mjs.map +1 -0
- package/dist/chunk-FZRTAML3.mjs +1 -0
- package/dist/chunk-FZRTAML3.mjs.map +1 -0
- package/dist/chunk-NY22GB3E.mjs +311 -0
- package/dist/chunk-NY22GB3E.mjs.map +1 -0
- package/dist/chunk-QCMWPIG7.mjs +320 -0
- package/dist/chunk-QCMWPIG7.mjs.map +1 -0
- package/dist/chunk-U27ZVCP7.mjs +247 -0
- package/dist/chunk-U27ZVCP7.mjs.map +1 -0
- package/dist/components/content/index.css +132 -0
- package/dist/components/content/index.css.map +1 -0
- package/dist/components/content/index.d.mts +17 -0
- package/dist/components/content/index.d.ts +17 -0
- package/dist/components/content/index.js +102 -0
- package/dist/components/content/index.js.map +1 -0
- package/dist/components/content/index.mjs +7 -0
- package/dist/components/content/index.mjs.map +1 -0
- package/dist/components/forms/index.css +307 -0
- package/dist/components/forms/index.css.map +1 -0
- package/dist/components/forms/index.d.mts +68 -0
- package/dist/components/forms/index.d.ts +68 -0
- package/dist/components/forms/index.js +357 -0
- package/dist/components/forms/index.js.map +1 -0
- package/dist/components/forms/index.mjs +9 -0
- package/dist/components/forms/index.mjs.map +1 -0
- package/dist/components/gallery/index.css +229 -0
- package/dist/components/gallery/index.css.map +1 -0
- package/dist/components/gallery/index.d.mts +29 -0
- package/dist/components/gallery/index.d.ts +29 -0
- package/dist/components/gallery/index.js +187 -0
- package/dist/components/gallery/index.js.map +1 -0
- package/dist/components/gallery/index.mjs +9 -0
- package/dist/components/gallery/index.mjs.map +1 -0
- package/dist/components/index.css +1181 -0
- package/dist/components/index.css.map +1 -0
- package/dist/components/index.d.mts +8 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +1317 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +50 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/components/layout/index.css +168 -0
- package/dist/components/layout/index.css.map +1 -0
- package/dist/components/layout/index.d.mts +55 -0
- package/dist/components/layout/index.d.ts +55 -0
- package/dist/components/layout/index.js +224 -0
- package/dist/components/layout/index.js.map +1 -0
- package/dist/components/layout/index.mjs +11 -0
- package/dist/components/layout/index.mjs.map +1 -0
- package/dist/components/navigation/index.css +229 -0
- package/dist/components/navigation/index.css.map +1 -0
- package/dist/components/navigation/index.d.mts +76 -0
- package/dist/components/navigation/index.d.ts +76 -0
- package/dist/components/navigation/index.js +347 -0
- package/dist/components/navigation/index.js.map +1 -0
- package/dist/components/navigation/index.mjs +7 -0
- package/dist/components/navigation/index.mjs.map +1 -0
- package/dist/components/social/index.css +116 -0
- package/dist/components/social/index.css.map +1 -0
- package/dist/components/social/index.d.mts +55 -0
- package/dist/components/social/index.d.ts +55 -0
- package/dist/components/social/index.js +280 -0
- package/dist/components/social/index.js.map +1 -0
- package/dist/components/social/index.mjs +21 -0
- package/dist/components/social/index.mjs.map +1 -0
- package/dist/index.css +1181 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1317 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +50 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
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 };
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/components/navigation/index.ts
|
|
31
|
+
var navigation_exports = {};
|
|
32
|
+
__export(navigation_exports, {
|
|
33
|
+
XNavbar: () => XNavbar
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(navigation_exports);
|
|
36
|
+
|
|
37
|
+
// src/components/navigation/xnavbar/XNavbar.tsx
|
|
38
|
+
var import_react = require("react");
|
|
39
|
+
var import_framer_motion = require("framer-motion");
|
|
40
|
+
var import_link = __toESM(require("next/link"));
|
|
41
|
+
var import_navigation = require("next/navigation");
|
|
42
|
+
|
|
43
|
+
// src/components/navigation/xnavbar/XNavbar.module.css
|
|
44
|
+
var XNavbar_default = {};
|
|
45
|
+
|
|
46
|
+
// src/components/navigation/xnavbar/XNavbar.tsx
|
|
47
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
48
|
+
var iconTrayRightVariants = {
|
|
49
|
+
hidden: { opacity: 0, x: -6, pointerEvents: "none" },
|
|
50
|
+
visible: { opacity: 1, x: 0, pointerEvents: "none", transition: { duration: 0.18 } }
|
|
51
|
+
};
|
|
52
|
+
var iconTrayLeftVariants = {
|
|
53
|
+
hidden: { opacity: 0, x: 6, pointerEvents: "none" },
|
|
54
|
+
visible: { opacity: 1, x: 0, pointerEvents: "none", transition: { duration: 0.18 } }
|
|
55
|
+
};
|
|
56
|
+
var topVariants = { closed: { rotate: 0 }, opened: { rotate: 45 } };
|
|
57
|
+
var centerVariants = { closed: { opacity: 1 }, opened: { opacity: 0 } };
|
|
58
|
+
var bottomVariants = { closed: { rotate: 0 }, opened: { rotate: -45 } };
|
|
59
|
+
var listVariants = {
|
|
60
|
+
closed: { x: "100vw" },
|
|
61
|
+
opened: { x: 0, transition: { when: "beforeChildren", staggerChildren: 0.02 } }
|
|
62
|
+
};
|
|
63
|
+
var itemVariants = {
|
|
64
|
+
closed: { x: -10, opacity: 0 },
|
|
65
|
+
opened: { x: 0, opacity: 1 }
|
|
66
|
+
};
|
|
67
|
+
function renderIcon(icon, size, color) {
|
|
68
|
+
if (typeof icon === "function") return icon(size, color);
|
|
69
|
+
return icon;
|
|
70
|
+
}
|
|
71
|
+
function XNavLink({ link, onClick, mobile }) {
|
|
72
|
+
const pathname = (0, import_navigation.usePathname)();
|
|
73
|
+
const isActive = link.url === "/" ? pathname === "/" : pathname?.startsWith(link.url);
|
|
74
|
+
const baseClass = mobile ? XNavbar_default.mobileNavLink : XNavbar_default.navLink;
|
|
75
|
+
const activeClass = mobile ? XNavbar_default.mobileNavLinkActive : XNavbar_default.navLinkActive;
|
|
76
|
+
const externalClass = link.external ? XNavbar_default.navLinkExternal : "";
|
|
77
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
78
|
+
import_link.default,
|
|
79
|
+
{
|
|
80
|
+
href: link.url,
|
|
81
|
+
onClick,
|
|
82
|
+
target: link.external ? "_blank" : void 0,
|
|
83
|
+
rel: link.external ? "noopener noreferrer" : void 0,
|
|
84
|
+
"aria-label": `Ir a ${link.title}`,
|
|
85
|
+
"aria-current": isActive ? "page" : void 0,
|
|
86
|
+
className: [baseClass, isActive ? activeClass : "", externalClass].filter(Boolean).join(" "),
|
|
87
|
+
children: link.title
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
function XNavbar({
|
|
92
|
+
linksLeft = [],
|
|
93
|
+
linksRight = [],
|
|
94
|
+
logo = "X",
|
|
95
|
+
logoAsThemeToggle = true,
|
|
96
|
+
onLogoClick,
|
|
97
|
+
themeIcons,
|
|
98
|
+
defaultTheme = "light",
|
|
99
|
+
storageKey = "theme",
|
|
100
|
+
linkColor,
|
|
101
|
+
linkHoverColor,
|
|
102
|
+
linkActiveColor,
|
|
103
|
+
iconColor,
|
|
104
|
+
iconHoverColor,
|
|
105
|
+
iconSize = 22,
|
|
106
|
+
hamburgerColor,
|
|
107
|
+
hamburgerBarWidth,
|
|
108
|
+
hamburgerBarThickness,
|
|
109
|
+
cssVars,
|
|
110
|
+
labelOpen = "Abrir men\xFA",
|
|
111
|
+
labelClose = "Cerrar men\xFA",
|
|
112
|
+
labelDark = "Oscuro",
|
|
113
|
+
labelLight = "Claro",
|
|
114
|
+
className
|
|
115
|
+
}) {
|
|
116
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
117
|
+
const [hoverX, setHoverX] = (0, import_react.useState)(false);
|
|
118
|
+
const [theme, setTheme] = (0, import_react.useState)(defaultTheme);
|
|
119
|
+
(0, import_react.useEffect)(() => {
|
|
120
|
+
const saved = typeof window !== "undefined" && localStorage.getItem(storageKey);
|
|
121
|
+
applyTheme(saved ?? defaultTheme);
|
|
122
|
+
}, []);
|
|
123
|
+
function applyTheme(t) {
|
|
124
|
+
setTheme(t);
|
|
125
|
+
const root = document.documentElement;
|
|
126
|
+
if (t === "dark") root.setAttribute("data-theme", "dark");
|
|
127
|
+
else root.removeAttribute("data-theme");
|
|
128
|
+
localStorage.setItem(storageKey, t);
|
|
129
|
+
}
|
|
130
|
+
function toggleTheme() {
|
|
131
|
+
applyTheme(theme === "dark" ? "light" : "dark");
|
|
132
|
+
}
|
|
133
|
+
(0, import_react.useEffect)(() => {
|
|
134
|
+
document.documentElement.style.overflow = open ? "hidden" : "";
|
|
135
|
+
return () => {
|
|
136
|
+
document.documentElement.style.overflow = "";
|
|
137
|
+
};
|
|
138
|
+
}, [open]);
|
|
139
|
+
(0, import_react.useEffect)(() => {
|
|
140
|
+
if (!open) return;
|
|
141
|
+
const onKey = (e) => {
|
|
142
|
+
if (e.key === "Escape") setOpen(false);
|
|
143
|
+
};
|
|
144
|
+
window.addEventListener("keydown", onKey);
|
|
145
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
146
|
+
}, [open]);
|
|
147
|
+
const allLinks = [...linksLeft, ...linksRight];
|
|
148
|
+
const headerStyle = {
|
|
149
|
+
...linkColor && { "--xnav-link-color": linkColor },
|
|
150
|
+
...linkHoverColor && { "--xnav-link-hover": linkHoverColor },
|
|
151
|
+
...linkActiveColor && { "--xnav-link-active": linkActiveColor },
|
|
152
|
+
...iconColor && { "--xnav-icon-color": iconColor },
|
|
153
|
+
...iconHoverColor && { "--xnav-icon-hover": iconHoverColor },
|
|
154
|
+
...hamburgerColor && { "--xnav-bar-color": hamburgerColor },
|
|
155
|
+
...hamburgerBarWidth && { "--xnav-bar-w": hamburgerBarWidth },
|
|
156
|
+
...hamburgerBarThickness && { "--xnav-bar-h": hamburgerBarThickness },
|
|
157
|
+
...cssVars
|
|
158
|
+
};
|
|
159
|
+
const handleLogoClick = () => {
|
|
160
|
+
if (logoAsThemeToggle) {
|
|
161
|
+
toggleTheme();
|
|
162
|
+
} else {
|
|
163
|
+
onLogoClick?.();
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const logoAriaLabel = logoAsThemeToggle ? `Cambiar a tema ${theme === "dark" ? "claro" : "oscuro"}` : void 0;
|
|
167
|
+
const logoTitle = logoAsThemeToggle ? theme === "dark" ? "Cambiar a tema claro" : "Cambiar a tema oscuro" : void 0;
|
|
168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
169
|
+
"header",
|
|
170
|
+
{
|
|
171
|
+
className: [XNavbar_default.header, className].filter(Boolean).join(" "),
|
|
172
|
+
style: headerStyle,
|
|
173
|
+
role: "banner",
|
|
174
|
+
children: [
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("nav", { className: XNavbar_default.desktopNav, "aria-label": "Navegaci\xF3n principal", children: [
|
|
176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: XNavbar_default.desktopLinksLeft, children: linksLeft.map((link) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XNavLink, { link }, link.url + link.title)) }),
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: XNavbar_default.logoSlot, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
178
|
+
"div",
|
|
179
|
+
{
|
|
180
|
+
className: XNavbar_default.logoWrapper,
|
|
181
|
+
onMouseEnter: () => setHoverX(true),
|
|
182
|
+
onMouseLeave: () => setHoverX(false),
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
185
|
+
"button",
|
|
186
|
+
{
|
|
187
|
+
type: "button",
|
|
188
|
+
onClick: handleLogoClick,
|
|
189
|
+
"aria-label": logoAriaLabel,
|
|
190
|
+
title: logoTitle,
|
|
191
|
+
className: XNavbar_default.logoBtn,
|
|
192
|
+
children: logo
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
logoAsThemeToggle && themeIcons && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
196
|
+
import_framer_motion.motion.div,
|
|
197
|
+
{
|
|
198
|
+
initial: false,
|
|
199
|
+
animate: hoverX ? "visible" : "hidden",
|
|
200
|
+
variants: iconTrayRightVariants,
|
|
201
|
+
className: `${XNavbar_default.iconTray} ${XNavbar_default.iconTrayRight}`,
|
|
202
|
+
style: {
|
|
203
|
+
color: (hoverX ? iconHoverColor ?? iconColor : iconColor) || void 0
|
|
204
|
+
},
|
|
205
|
+
"aria-hidden": true,
|
|
206
|
+
children: renderIcon(themeIcons.toDark, iconSize, iconColor)
|
|
207
|
+
}
|
|
208
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
209
|
+
import_framer_motion.motion.div,
|
|
210
|
+
{
|
|
211
|
+
initial: false,
|
|
212
|
+
animate: hoverX ? "visible" : "hidden",
|
|
213
|
+
variants: iconTrayLeftVariants,
|
|
214
|
+
className: `${XNavbar_default.iconTray} ${XNavbar_default.iconTrayLeft}`,
|
|
215
|
+
style: {
|
|
216
|
+
color: (hoverX ? iconHoverColor ?? iconColor : iconColor) || void 0
|
|
217
|
+
},
|
|
218
|
+
"aria-hidden": true,
|
|
219
|
+
children: renderIcon(themeIcons.toLight, iconSize, iconColor)
|
|
220
|
+
}
|
|
221
|
+
) })
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
) }),
|
|
225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: XNavbar_default.desktopLinksRight, children: linksRight.map((link) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XNavLink, { link }, link.url + link.title)) })
|
|
226
|
+
] }),
|
|
227
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: XNavbar_default.mobileToggle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
228
|
+
"button",
|
|
229
|
+
{
|
|
230
|
+
"aria-label": open ? labelClose : labelOpen,
|
|
231
|
+
"aria-expanded": open,
|
|
232
|
+
"aria-controls": "xnavbar-mobile-menu",
|
|
233
|
+
onClick: () => setOpen((p) => !p),
|
|
234
|
+
className: XNavbar_default.hamburgerBtn,
|
|
235
|
+
title: open ? labelClose : labelOpen,
|
|
236
|
+
children: [
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
238
|
+
import_framer_motion.motion.div,
|
|
239
|
+
{
|
|
240
|
+
variants: topVariants,
|
|
241
|
+
initial: "closed",
|
|
242
|
+
animate: open ? "opened" : "closed",
|
|
243
|
+
className: XNavbar_default.bar,
|
|
244
|
+
style: { originX: "left" },
|
|
245
|
+
"aria-hidden": true
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
249
|
+
import_framer_motion.motion.div,
|
|
250
|
+
{
|
|
251
|
+
variants: centerVariants,
|
|
252
|
+
initial: "closed",
|
|
253
|
+
animate: open ? "opened" : "closed",
|
|
254
|
+
className: XNavbar_default.bar,
|
|
255
|
+
"aria-hidden": true
|
|
256
|
+
}
|
|
257
|
+
),
|
|
258
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
259
|
+
import_framer_motion.motion.div,
|
|
260
|
+
{
|
|
261
|
+
variants: bottomVariants,
|
|
262
|
+
initial: "closed",
|
|
263
|
+
animate: open ? "opened" : "closed",
|
|
264
|
+
className: XNavbar_default.bar,
|
|
265
|
+
style: { originX: "left" },
|
|
266
|
+
"aria-hidden": true
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
) }),
|
|
272
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
273
|
+
import_framer_motion.motion.div,
|
|
274
|
+
{
|
|
275
|
+
id: "xnavbar-mobile-menu",
|
|
276
|
+
variants: listVariants,
|
|
277
|
+
initial: "closed",
|
|
278
|
+
animate: "opened",
|
|
279
|
+
className: XNavbar_default.mobileOverlay,
|
|
280
|
+
role: "dialog",
|
|
281
|
+
"aria-modal": "true",
|
|
282
|
+
"aria-label": "Men\xFA de navegaci\xF3n",
|
|
283
|
+
children: [
|
|
284
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
285
|
+
"button",
|
|
286
|
+
{
|
|
287
|
+
"aria-label": labelClose,
|
|
288
|
+
onClick: () => setOpen(false),
|
|
289
|
+
className: XNavbar_default.mobileCloseBtn,
|
|
290
|
+
style: { WebkitTapHighlightColor: "transparent" },
|
|
291
|
+
children: [
|
|
292
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
293
|
+
"span",
|
|
294
|
+
{
|
|
295
|
+
"aria-hidden": true,
|
|
296
|
+
className: XNavbar_default.closeBar,
|
|
297
|
+
style: { transform: "rotate(45deg)" }
|
|
298
|
+
}
|
|
299
|
+
),
|
|
300
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
301
|
+
"span",
|
|
302
|
+
{
|
|
303
|
+
"aria-hidden": true,
|
|
304
|
+
className: XNavbar_default.closeBar,
|
|
305
|
+
style: { transform: "rotate(-45deg)" }
|
|
306
|
+
}
|
|
307
|
+
),
|
|
308
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labelClose })
|
|
309
|
+
]
|
|
310
|
+
}
|
|
311
|
+
),
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.motion.div, { variants: itemVariants, className: XNavbar_default.mobileLogo, children: logo }),
|
|
313
|
+
allLinks.map((link) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.motion.div, { variants: itemVariants, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
314
|
+
XNavLink,
|
|
315
|
+
{
|
|
316
|
+
link,
|
|
317
|
+
onClick: () => setOpen(false),
|
|
318
|
+
mobile: true
|
|
319
|
+
}
|
|
320
|
+
) }, link.url + link.title)),
|
|
321
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
322
|
+
import_framer_motion.motion.button,
|
|
323
|
+
{
|
|
324
|
+
variants: itemVariants,
|
|
325
|
+
onClick: toggleTheme,
|
|
326
|
+
className: XNavbar_default.themeToggleMobile,
|
|
327
|
+
children: themeIcons ? theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
328
|
+
renderIcon(themeIcons.toDark, iconSize, iconColor),
|
|
329
|
+
labelDark
|
|
330
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
331
|
+
renderIcon(themeIcons.toLight, iconSize, iconColor),
|
|
332
|
+
labelLight
|
|
333
|
+
] }) : theme === "light" ? labelDark : labelLight
|
|
334
|
+
}
|
|
335
|
+
)
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
)
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
344
|
+
0 && (module.exports = {
|
|
345
|
+
XNavbar
|
|
346
|
+
});
|
|
347
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* src/components/social/xsocialcontact/XSocialContact.module.css */
|
|
2
|
+
.container {
|
|
3
|
+
--columns: 3;
|
|
4
|
+
--gap: 1.5rem;
|
|
5
|
+
--padding: 1.5rem;
|
|
6
|
+
--text-size: 1rem;
|
|
7
|
+
--alignment: center;
|
|
8
|
+
--text-align: center;
|
|
9
|
+
--icon-gap: 1.5rem;
|
|
10
|
+
--border-radius: 0.5rem;
|
|
11
|
+
--bg-color: transparent;
|
|
12
|
+
--icon-color: currentColor;
|
|
13
|
+
--icon-hover-color: currentColor;
|
|
14
|
+
--border-color: transparent;
|
|
15
|
+
--border-width: 0px;
|
|
16
|
+
--border-style: solid;
|
|
17
|
+
--text-color: inherit;
|
|
18
|
+
display: grid;
|
|
19
|
+
grid-template-columns: repeat(var(--columns), 1fr);
|
|
20
|
+
gap: var(--gap);
|
|
21
|
+
padding: var(--padding);
|
|
22
|
+
background-color: var(--bg-color);
|
|
23
|
+
border: var(--border-width) var(--border-style) var(--border-color);
|
|
24
|
+
border-radius: var(--border-radius);
|
|
25
|
+
justify-items: var(--alignment);
|
|
26
|
+
}
|
|
27
|
+
.small {
|
|
28
|
+
--icon-gap: 1rem;
|
|
29
|
+
--gap: 1rem;
|
|
30
|
+
--padding: 1rem;
|
|
31
|
+
--text-size: 0.875rem;
|
|
32
|
+
}
|
|
33
|
+
.medium {
|
|
34
|
+
--icon-gap: 1.5rem;
|
|
35
|
+
--gap: 1.5rem;
|
|
36
|
+
--padding: 1.5rem;
|
|
37
|
+
--text-size: 1rem;
|
|
38
|
+
}
|
|
39
|
+
.large {
|
|
40
|
+
--icon-gap: 2rem;
|
|
41
|
+
--gap: 2rem;
|
|
42
|
+
--padding: 2rem;
|
|
43
|
+
--text-size: 1.125rem;
|
|
44
|
+
}
|
|
45
|
+
.rows1 {
|
|
46
|
+
grid-template-rows: auto;
|
|
47
|
+
}
|
|
48
|
+
.rows2 {
|
|
49
|
+
grid-template-rows: repeat(2, auto);
|
|
50
|
+
}
|
|
51
|
+
.rows3 {
|
|
52
|
+
grid-template-rows: repeat(3, auto);
|
|
53
|
+
}
|
|
54
|
+
.rows4 {
|
|
55
|
+
grid-template-rows: repeat(4, auto);
|
|
56
|
+
}
|
|
57
|
+
.item {
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
align-items: center;
|
|
61
|
+
gap: calc(var(--icon-gap) * 0.5);
|
|
62
|
+
text-decoration: none;
|
|
63
|
+
transition: opacity 0.2s ease;
|
|
64
|
+
color: inherit;
|
|
65
|
+
}
|
|
66
|
+
.item:hover {
|
|
67
|
+
opacity: 0.8;
|
|
68
|
+
}
|
|
69
|
+
.iconWrapper {
|
|
70
|
+
--item-icon-color: var(--icon-color);
|
|
71
|
+
--item-icon-hover-color: var(--icon-hover-color);
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
width: var(--icon-gap);
|
|
76
|
+
height: var(--icon-gap);
|
|
77
|
+
color: var(--item-icon-color);
|
|
78
|
+
transition: color 0.2s ease;
|
|
79
|
+
}
|
|
80
|
+
.item:hover .iconWrapper {
|
|
81
|
+
color: var(--item-icon-hover-color);
|
|
82
|
+
}
|
|
83
|
+
.text {
|
|
84
|
+
font-size: var(--text-size);
|
|
85
|
+
color: var(--text-color);
|
|
86
|
+
text-align: var(--text-align);
|
|
87
|
+
word-break: break-word;
|
|
88
|
+
max-width: 100%;
|
|
89
|
+
}
|
|
90
|
+
@media (max-width: 768px) {
|
|
91
|
+
.container {
|
|
92
|
+
--columns: 2;
|
|
93
|
+
--gap: calc(var(--gap) * 0.75);
|
|
94
|
+
--padding: calc(var(--padding) * 0.75);
|
|
95
|
+
}
|
|
96
|
+
.rows2,
|
|
97
|
+
.rows3,
|
|
98
|
+
.rows4 {
|
|
99
|
+
grid-template-columns: repeat(2, 1fr);
|
|
100
|
+
grid-template-rows: repeat(2, auto);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
@media (max-width: 480px) {
|
|
104
|
+
.container {
|
|
105
|
+
--columns: 1;
|
|
106
|
+
--gap: calc(var(--gap) * 0.5);
|
|
107
|
+
--padding: calc(var(--padding) * 0.5);
|
|
108
|
+
}
|
|
109
|
+
.rows2,
|
|
110
|
+
.rows3,
|
|
111
|
+
.rows4 {
|
|
112
|
+
grid-template-columns: 1fr;
|
|
113
|
+
grid-template-rows: auto;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/social/xsocialcontact/XSocialContact.module.css"],"sourcesContent":["/* XSocialContact Styles */\n\n.container {\n --columns: 3;\n --gap: 1.5rem;\n --padding: 1.5rem;\n --text-size: 1rem;\n --alignment: center;\n --text-align: center;\n --icon-gap: 1.5rem;\n --border-radius: 0.5rem;\n --bg-color: transparent;\n --icon-color: currentColor;\n --icon-hover-color: currentColor;\n --border-color: transparent;\n --border-width: 0px;\n --border-style: solid;\n --text-color: inherit;\n\n display: grid;\n grid-template-columns: repeat(var(--columns), 1fr);\n gap: var(--gap);\n padding: var(--padding);\n background-color: var(--bg-color);\n border: var(--border-width) var(--border-style) var(--border-color);\n border-radius: var(--border-radius);\n justify-items: var(--alignment);\n}\n\n/* Size variants */\n.small {\n --icon-gap: 1rem;\n --gap: 1rem;\n --padding: 1rem;\n --text-size: 0.875rem;\n}\n\n.medium {\n --icon-gap: 1.5rem;\n --gap: 1.5rem;\n --padding: 1.5rem;\n --text-size: 1rem;\n}\n\n.large {\n --icon-gap: 2rem;\n --gap: 2rem;\n --padding: 2rem;\n --text-size: 1.125rem;\n}\n\n/* Rows configuration */\n.rows1 {\n grid-template-rows: auto;\n}\n\n.rows2 {\n grid-template-rows: repeat(2, auto);\n}\n\n.rows3 {\n grid-template-rows: repeat(3, auto);\n}\n\n.rows4 {\n grid-template-rows: repeat(4, auto);\n}\n\n/* Item styling */\n.item {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: calc(var(--icon-gap) * 0.5);\n text-decoration: none;\n transition: opacity 0.2s ease;\n color: inherit;\n}\n\n.item:hover {\n opacity: 0.8;\n}\n\n.iconWrapper {\n --item-icon-color: var(--icon-color);\n --item-icon-hover-color: var(--icon-hover-color);\n \n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--icon-gap);\n height: var(--icon-gap);\n color: var(--item-icon-color);\n transition: color 0.2s ease;\n}\n\n.item:hover .iconWrapper {\n color: var(--item-icon-hover-color);\n}\n\n.text {\n font-size: var(--text-size);\n color: var(--text-color);\n text-align: var(--text-align);\n word-break: break-word;\n max-width: 100%;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .container {\n --columns: 2;\n --gap: calc(var(--gap) * 0.75);\n --padding: calc(var(--padding) * 0.75);\n }\n \n .rows2,\n .rows3,\n .rows4 {\n grid-template-columns: repeat(2, 1fr);\n grid-template-rows: repeat(2, auto);\n }\n}\n\n@media (max-width: 480px) {\n .container {\n --columns: 1;\n --gap: calc(var(--gap) * 0.5);\n --padding: calc(var(--padding) * 0.5);\n }\n \n .rows2,\n .rows3,\n .rows4 {\n grid-template-columns: 1fr;\n grid-template-rows: auto;\n }\n}\n"],"mappings":";AAEA,CAAC;AACG,aAAW;AACX,SAAO;AACP,aAAW;AACX,eAAa;AACb,eAAa;AACb,gBAAc;AACd,cAAY;AACZ,mBAAiB;AACjB,cAAY;AACZ,gBAAc;AACd,sBAAoB;AACpB,kBAAgB;AAChB,kBAAgB;AAChB,kBAAgB;AAChB,gBAAc;AAEd,WAAS;AACT,yBAAuB,OAAO,IAAI,UAAU,EAAE;AAC9C,OAAK,IAAI;AACT,WAAS,IAAI;AACb,oBAAkB,IAAI;AACtB,UAAQ,IAAI,gBAAgB,IAAI,gBAAgB,IAAI;AACpD,iBAAe,IAAI;AACnB,iBAAe,IAAI;AACvB;AAGA,CAAC;AACG,cAAY;AACZ,SAAO;AACP,aAAW;AACX,eAAa;AACjB;AAEA,CAAC;AACG,cAAY;AACZ,SAAO;AACP,aAAW;AACX,eAAa;AACjB;AAEA,CAAC;AACG,cAAY;AACZ,SAAO;AACP,aAAW;AACX,eAAa;AACjB;AAGA,CAAC;AACG,sBAAoB;AACxB;AAEA,CAAC;AACG,sBAAoB,OAAO,CAAC,EAAE;AAClC;AAEA,CAAC;AACG,sBAAoB,OAAO,CAAC,EAAE;AAClC;AAEA,CAAC;AACG,sBAAoB,OAAO,CAAC,EAAE;AAClC;AAGA,CAAC;AACG,WAAS;AACT,kBAAgB;AAChB,eAAa;AACb,OAAK,KAAK,IAAI,YAAY,EAAE;AAC5B,mBAAiB;AACjB,cAAY,QAAQ,KAAK;AACzB,SAAO;AACX;AAEA,CAVC,IAUI;AACD,WAAS;AACb;AAEA,CAAC;AACG,qBAAmB,IAAI;AACvB,2BAAyB,IAAI;AAE7B,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,SAAO,IAAI;AACX,UAAQ,IAAI;AACZ,SAAO,IAAI;AACX,cAAY,MAAM,KAAK;AAC3B;AAEA,CA3BC,IA2BI,OAAO,CAbX;AAcG,SAAO,IAAI;AACf;AAEA,CAAC;AACG,aAAW,IAAI;AACf,SAAO,IAAI;AACX,cAAY,IAAI;AAChB,cAAY;AACZ,aAAW;AACf;AAGA,QAAO,WAAY;AACf,GA5GH;AA6GO,eAAW;AACX,WAAO,KAAK,IAAI,OAAO,EAAE;AACzB,eAAW,KAAK,IAAI,WAAW,EAAE;AACrC;AAEA,GA5DH;AAAA,EA6DG,CAzDH;AAAA,EA0DG,CAtDH;AAuDO,2BAAuB,OAAO,CAAC,EAAE;AACjC,wBAAoB,OAAO,CAAC,EAAE;AAClC;AACJ;AAEA,QAAO,WAAY;AACf,GA3HH;AA4HO,eAAW;AACX,WAAO,KAAK,IAAI,OAAO,EAAE;AACzB,eAAW,KAAK,IAAI,WAAW,EAAE;AACrC;AAEA,GA3EH;AAAA,EA4EG,CAxEH;AAAA,EAyEG,CArEH;AAsEO,2BAAuB;AACvB,wBAAoB;AACxB;AACJ;","names":[]}
|