@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
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import "./chunk-FZRTAML3.mjs";
|
|
2
|
-
import {
|
|
3
|
-
XInteractivePhrase
|
|
4
|
-
} from "./chunk-5G4P2E76.mjs";
|
|
5
2
|
import {
|
|
6
3
|
XContactForm,
|
|
7
4
|
XNewsletter
|
|
8
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TKT37LIX.mjs";
|
|
9
6
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./chunk-2OAXRRVQ.mjs";
|
|
7
|
+
XNavbar
|
|
8
|
+
} from "./chunk-TG3B4GAW.mjs";
|
|
13
9
|
import {
|
|
14
10
|
XFooter,
|
|
15
11
|
XSeparator,
|
|
16
12
|
XZigZagLayout
|
|
17
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-UROP4J6G.mjs";
|
|
18
14
|
import {
|
|
19
|
-
|
|
20
|
-
} from "./chunk-
|
|
15
|
+
XInteractivePhrase
|
|
16
|
+
} from "./chunk-34NJCJUI.mjs";
|
|
17
|
+
import {
|
|
18
|
+
XMicroGalleryText_default,
|
|
19
|
+
XStaticGallery
|
|
20
|
+
} from "./chunk-MYFPSHSQ.mjs";
|
|
21
21
|
import {
|
|
22
22
|
XEmailIcon,
|
|
23
23
|
XGitHubIcon,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
XTelegramIcon,
|
|
28
28
|
XTwitterIcon,
|
|
29
29
|
XWhatsappIcon
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-2H7TVDE7.mjs";
|
|
31
31
|
export {
|
|
32
32
|
XContactForm,
|
|
33
33
|
XEmailIcon,
|
|
@@ -47,4 +47,4 @@ export {
|
|
|
47
47
|
XWhatsappIcon,
|
|
48
48
|
XZigZagLayout
|
|
49
49
|
};
|
|
50
|
-
//# sourceMappingURL=index.mjs.map
|
|
50
|
+
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xscriptor/xcomponents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Reusable React/Next.js UI components by Xscriptor.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"import": "./dist/index.mjs",
|
|
28
28
|
"require": "./dist/index.js"
|
|
29
29
|
},
|
|
30
|
+
"./styles.css": "./dist/index.css",
|
|
30
31
|
"./components": {
|
|
31
32
|
"types": "./dist/components/index.d.ts",
|
|
32
33
|
"import": "./dist/components/index.mjs",
|
|
@@ -72,15 +73,16 @@
|
|
|
72
73
|
"devDependencies": {
|
|
73
74
|
"@types/react": "^18.3.16",
|
|
74
75
|
"@types/react-dom": "^18.3.5",
|
|
76
|
+
"esbuild": "^0.25.9",
|
|
75
77
|
"framer-motion": "^11.15.0",
|
|
76
78
|
"next": "^15.1.3",
|
|
77
|
-
"tsup": "^8.3.5",
|
|
78
79
|
"typescript": "^5.7.2"
|
|
79
80
|
},
|
|
80
81
|
"scripts": {
|
|
81
|
-
"build": "
|
|
82
|
+
"build": "npm run clean && node ./scripts/build.mjs && npm run build:types",
|
|
83
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
82
84
|
"clean": "rm -rf dist",
|
|
83
|
-
"prepare:build": "npm run
|
|
85
|
+
"prepare:build": "npm run build",
|
|
84
86
|
"prepublishOnly": "npm run prepare:build"
|
|
85
87
|
}
|
|
86
88
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/gallery/xmicrogallerytext/XMicroGalleryText.tsx","../src/components/gallery/xmicrogallerytext/XMicroGalleryText.module.css","../src/components/gallery/xstaticgallery/XStaticGallery.tsx","../src/components/gallery/xstaticgallery/XStaticGallery.module.css"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\nimport Image from 'next/image';\nimport { motion } from 'framer-motion';\nimport styles from './XMicroGalleryText.module.css';\n\nexport interface XMicroGalleryImage {\n src: string;\n alt: string;\n}\n\nexport interface XMicroGalleryTextProps {\n images: XMicroGalleryImage[];\n text: React.ReactNode;\n textPosition?: 'left' | 'right';\n textAlign?: 'left' | 'right' | 'center';\n autoShuffle?: boolean;\n shuffleInterval?: number;\n}\n\nconst DISPLAY_COUNT = 3;\n\nconst XMicroGalleryText: React.FC<XMicroGalleryTextProps> = ({ \n images, \n text, \n textPosition = 'left',\n textAlign = 'left',\n autoShuffle = false,\n shuffleInterval = 5000\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [startIndex, setStartIndex] = React.useState(0);\n\n const visibleImages = React.useMemo(() => {\n const result: XMicroGalleryImage[] = [];\n for (let i = 0; i < DISPLAY_COUNT; i++) {\n result.push(images[(startIndex + i) % images.length]);\n }\n return result;\n }, [images, startIndex]);\n\n React.useEffect(() => {\n if (!autoShuffle || images.length <= DISPLAY_COUNT) return;\n\n const intervalId = setInterval(() => {\n setStartIndex((prev) => (prev + 1) % images.length);\n }, shuffleInterval);\n\n return () => clearInterval(intervalId);\n }, [autoShuffle, shuffleInterval, images.length]);\n\n const [isVisible, setIsVisible] = React.useState(false);\n\n useEffect(() => {\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n },\n {\n threshold: 0.1,\n rootMargin: '0px 0px -50px 0px'\n }\n );\n\n if (containerRef.current) {\n observer.observe(containerRef.current);\n }\n\n return () => observer.disconnect();\n }, []);\n\n const isTextRight = textPosition === 'right';\n\n const alignClass = {\n left: styles.textLeft,\n right: styles.textRight,\n center: styles.textCenter,\n }[textAlign];\n\n return (\n <div ref={containerRef} className={`${styles.container} ${isTextRight ? styles.reverse : ''}`}>\n <div className={`${styles.textContent} ${alignClass} ${isVisible ? styles.visible : ''}`}>\n {typeof text === 'string' ? (\n <div dangerouslySetInnerHTML={{ __html: text }} />\n ) : (\n text\n )}\n </div>\n \n <div className={styles.gallery}>\n <div className={styles.artisticGrid}>\n {visibleImages.map((image, index) => (\n <motion.div \n layout\n key={image.src} \n className={`${styles.imageWrapper} ${styles[`artistic${index + 1}`]} ${isVisible ? styles.visible : ''}`}\n style={{ transitionProperty: 'opacity, box-shadow' }}\n transition={{\n layout: { type: \"spring\", stiffness: 80, damping: 20 }\n }}\n >\n <Image\n src={image.src}\n alt={image.alt}\n fill\n className={styles.previewImage}\n sizes=\"(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw\"\n />\n </motion.div>\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nexport default XMicroGalleryText;\n",".container {\n display: flex;\n flex-direction: column;\n gap: 2rem;\n width: 100%;\n align-items: center;\n margin: 2rem 0;\n}\n\n@media (min-width: 1024px) {\n .container {\n flex-direction: row;\n align-items: center;\n gap: 4rem;\n }\n \n .reverse {\n flex-direction: row-reverse;\n }\n}\n\n.textContent {\n flex: 1;\n opacity: 0;\n transform: translateY(30px);\n transition: opacity 0.8s ease-out, transform 0.8s ease-out;\n color: var(--foreground);\n}\n\n.textContent.visible {\n opacity: 1;\n transform: translateY(0);\n}\n\n.textLeft {\n text-align: left;\n}\n\n.textRight {\n text-align: right;\n}\n\n.textCenter {\n text-align: center;\n}\n\n.textContent p,\n.textContent div,\n.textContent span,\n.textContent em,\n.textContent strong,\n.textContent a {\n text-align: inherit;\n max-width: none;\n margin-left: unset;\n margin-right: unset;\n}\n\n.gallery {\n flex: 1.5;\n width: 100%;\n}\n\n.artisticGrid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n grid-template-rows: 380px 220px;\n gap: 1rem;\n}\n\n.imageWrapper {\n position: relative;\n overflow: hidden;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);\n border-radius: 20px;\n opacity: 0;\n transform: translateY(50px) scale(0.95);\n transition: opacity 0.6s ease-out, transform 0.6s ease-out, box-shadow 0.3s ease;\n}\n\n.imageWrapper.visible {\n opacity: 1;\n transform: translateY(0) scale(1);\n}\n\n.imageWrapper:hover {\n transform: translateY(-5px);\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);\n}\n\n.previewImage {\n object-fit: cover;\n}\n\n.artisticGrid .artistic1 .previewImage {\n object-position: center top;\n transform: translateY(0);\n}\n\n.artistic1 {\n grid-column: 1 / 4;\n grid-row: 1 / 2;\n transition-delay: 0.2s;\n}\n\n.artistic2 {\n grid-column: 1 / 2;\n grid-row: 2 / 3;\n transition-delay: 0.3s;\n}\n\n.artistic3 {\n grid-column: 2 / 4;\n grid-row: 2 / 3;\n transition-delay: 0.4s;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .artisticGrid {\n grid-template-columns: 1fr;\n grid-template-rows: 240px 180px 180px;\n }\n \n .artistic1,\n .artistic2,\n .artistic3 {\n grid-column: 1 / 2;\n }\n \n .artistic1 {\n grid-row: 1 / 2;\n }\n \n .artistic2 {\n grid-row: 2 / 3;\n }\n \n .artistic3 {\n grid-row: 3 / 4;\n }\n}\n\n@media (max-width: 480px) {\n .artisticGrid {\n grid-template-rows: 200px 140px 140px;\n }\n}\n","\"use client\";\nimport React, { useEffect, useRef } from 'react';\nimport Image from 'next/image';\nimport styles from './XStaticGallery.module.css';\n\nexport interface XStaticGalleryImage {\n src: string;\n alt: string;\n}\n\nexport interface XStaticGalleryProps {\n images: XStaticGalleryImage[];\n columns?: 1 | 2 | 3 | 4 | 5;\n title?: string;\n}\n\nconst COLUMN_CLASSES: Record<number, string> = {\n 1: styles.cols1,\n 2: styles.cols2,\n 3: styles.cols3,\n 4: styles.cols4,\n 5: styles.cols5,\n};\n\nexport default function XStaticGallery({ images, columns = 4, title }: XStaticGalleryProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n entry.target.classList.add(styles.visible);\n }\n });\n },\n {\n threshold: 0.1,\n rootMargin: '0px 0px -50px 0px',\n }\n );\n\n const items = containerRef.current?.querySelectorAll(`.${styles.masonryItem}`);\n items?.forEach((el) => observer.observe(el));\n\n return () => observer.disconnect();\n }, []);\n\n const colClass = COLUMN_CLASSES[columns] || COLUMN_CLASSES[4];\n\n return (\n <div ref={containerRef} className={styles.galleryContainer}>\n {title && <h2 className={styles.galleryTitle}>{title}</h2>}\n\n <div className={`${styles.masonryGrid} ${colClass}`}>\n {images.map((image, index) => (\n <div key={index} className={styles.masonryItem}>\n <div className={styles.imageContainer}>\n <Image\n src={image.src}\n alt={image.alt}\n width={600}\n height={600}\n className={styles.galleryImage}\n loading=\"lazy\"\n sizes=\"(max-width: 640px) 100vw, (max-width: 768px) 50vw, (max-width: 1280px) 33vw, 25vw\"\n />\n <div className={styles.imageOverlay} />\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n",".galleryContainer {\n width: 100%;\n max-width: 80rem;\n margin: 0 auto;\n padding: 1rem 1rem 3rem;\n}\n\n.galleryTitle {\n font-size: 1.875rem;\n text-align: right;\n color: var(--primary);\n margin-bottom: 3rem;\n opacity: 0.8;\n}\n\n/* Masonry via CSS columns */\n.masonryGrid {\n gap: 1rem;\n}\n\n.masonryItem {\n break-inside: avoid;\n position: relative;\n border-radius: 1rem;\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n margin-bottom: 1rem;\n opacity: 0;\n transform: translateY(20px);\n transition: opacity 0.5s ease-out, transform 0.5s ease-out, box-shadow 0.3s ease;\n}\n\n.masonryItem.visible {\n opacity: 1;\n transform: translateY(0);\n}\n\n.masonryItem:hover {\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);\n}\n\n.imageContainer {\n position: relative;\n width: 100%;\n overflow: hidden;\n border-radius: 1rem;\n}\n\n.galleryImage {\n width: 100%;\n height: auto;\n object-fit: cover;\n display: block;\n transition: transform 0.5s ease-out;\n}\n\n.masonryItem:hover .galleryImage {\n transform: scale(1.05);\n}\n\n.imageOverlay {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0);\n transition: background 0.3s ease;\n pointer-events: none;\n}\n\n.masonryItem:hover .imageOverlay {\n background: rgba(0, 0, 0, 0.1);\n}\n\n/* Column count via CSS custom property */\n.cols1 { columns: 1; }\n.cols2 { columns: 2; }\n.cols3 { columns: 3; }\n.cols4 { columns: 4; }\n.cols5 { columns: 5; }\n\n/* Responsive overrides */\n@media (max-width: 1280px) {\n .cols4, .cols5 { columns: 3; }\n}\n\n@media (max-width: 768px) {\n .cols3, .cols4, .cols5 { columns: 2; }\n}\n\n@media (max-width: 640px) {\n .cols2, .cols3, .cols4, .cols5 { columns: 1; }\n}\n"],"mappings":"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","names":["XMicroGalleryText_default","useEffect","useRef","Image","jsx","jsxs","useRef","useEffect","Image"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/layout/xfooter/XFooter.tsx","../src/components/layout/xfooter/XFooter.module.css","../src/components/layout/xseparator/XSeparator.module.css","../src/components/layout/xseparator/XSeparator.tsx","../src/components/layout/xzigzaglayout/XZigZagLayout.tsx","../src/components/layout/xzigzaglayout/XZigZagLayout.module.css"],"sourcesContent":["import Link from \"next/link\";\nimport { CSSProperties } from \"react\";\nimport styles from \"./XFooter.module.css\";\n\nexport type XFooterLink = {\n label: string;\n href: string;\n};\n\nexport type CopyrightConfig = {\n text?: string;\n showYear?: boolean;\n customYear?: number | string;\n yearFirst?: boolean;\n};\n\nexport type XFooterProps = {\n links: XFooterLink[];\n copyright?: CopyrightConfig; \n layout?: \"horizontal\" | \"vertical\";\n columns?: 1 | 2 | 3 | 4;\n colors?: {\n bg?: string;\n text?: string;\n accent?: string;\n border?: string;\n };\n className?: string;\n};\nexport default function XFooter({\n links,\n copyright,\n layout = \"horizontal\",\n columns = 1,\n colors,\n className = \"\",\n}: XFooterProps) {\n \n const customStyles = {\n \"--xf-bg\": colors?.bg,\n \"--xf-text\": colors?.text,\n \"--xf-accent\": colors?.accent,\n \"--xf-border\": colors?.border,\n \"--xf-cols\": layout === \"horizontal\" ? columns : 1,\n } as CSSProperties;\n\n const currentYear = copyright?.customYear || new Date().getFullYear();\n const copyLabel = copyright?.text || \"Xscriptor\";\n\n return (\n <footer className={`${styles.XFooter} ${className}`} style={customStyles}>\n <div className={styles.container}>\n {/* Los links se organizan en el grid definido por --xf-cols */}\n <nav className={layout === \"vertical\" ? styles.navVertical : styles.nav}>\n {links.map((link, idx) => (\n <Link key={idx} href={link.href} className={styles.link}>\n {link.label}\n </Link>\n ))}\n </nav>\n\n {/* El copyright queda fuera del nav, por lo que hereda el centrado del container */}\n <div className={styles.copyright}>\n © {copyright?.yearFirst \n ? `${currentYear} ${copyLabel}` \n : `${copyLabel} ${currentYear}`}\n </div>\n </div>\n </footer>\n );\n}",".XFooter {\n width: 100%;\n background-color: var(--xf-bg, transparent);\n color: var(--xf-text, #333);\n padding: var(--xf-py, 0.9rem) 0.6rem;\n}\n\n.container {\n max-width: 1280px;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.6rem; /* Espacio entre los links y el copyright */\n}\n\n/* El nav es el que maneja las columnas de los links */\n.nav {\n display: grid;\n gap: 0.5rem 1.5rem; \n grid-template-columns: repeat(var(--xf-cols, 1), minmax(0, auto));\n justify-content: center;\n text-align: center;\n width: 100%;\n}\n\n.navVertical {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.75rem;\n}\n\n.link {\n color: var(--xf-accent, inherit);\n text-decoration: none;\n font-size: 0.9rem;\n transition: opacity 0.2s;\n white-space: nowrap; /* Evita que los links se rompan en dos líneas */\n}\n\n.link:hover {\n opacity: 0.7;\n}\n\n/* El copyright siempre irá al final y centrado por el flex del .container */\n.copyright {\n font-size: 0.75rem;\n opacity: 0.6;\n width: 100%;\n text-align: center;\n}",".separatorContainer {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n /* Variables para la X con fallbacks */\n --x-color: var(--separator-color); \n --x-bg: white;\n}\n\n.iconWrapper {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n background-color: var(--x-bg);\n padding: 0 10px;\n \n /* Aplicamos el color dinámico */\n color: var(--x-color);\n \n font-family: system-ui, sans-serif;\n font-weight: bold;\n font-size: 1.2rem;\n line-height: 1;\n user-select: none;\n}\n\n.separator {\n --separator-color: #e2e8f0;\n --separator-thickness: 1px;\n --separator-margin: 1rem;\n \n border: 0;\n background-color: var(--separator-color);\n}\n\n/* Variantes de Estilo */\n.dashed {\n background-color: transparent !important;\n border-bottom: var(--separator-thickness) dashed var(--separator-color);\n}\n\n.dotted {\n background-color: transparent !important;\n border-bottom: var(--separator-thickness) dotted var(--separator-color);\n}\n\n/* Efecto Desvanecido (Fading) */\n/* Usamos mask-image para que funcione con cualquier color de fondo */\n.faded {\n mask-image: linear-gradient(\n to right, \n transparent, \n black 20%, \n black 80%, \n transparent\n );\n}\n\n/* Ajuste para desvanecido vertical */\n.vertical.faded {\n mask-image: linear-gradient(\n to bottom, \n transparent, \n black 20%, \n black 80%, \n transparent\n );\n}\n\n.horizontal {\n width: 100%;\n height: var(--separator-thickness);\n margin: var(--separator-margin) 0;\n}\n\n.vertical {\n width: var(--separator-thickness);\n height: 100%;\n display: inline-block;\n margin: 0 var(--separator-margin);\n vertical-align: middle;\n}","import React from 'react';\nimport styles from './XSeparator.module.css';\n\nexport interface XSeparatorProps {\n orientation?: 'horizontal' | 'vertical';\n variant?: 'solid' | 'dashed' | 'dotted';\n isFaded?: boolean;\n hasX?: boolean;\n xColor?: string; // Nuevo: Color de la X\n xBg?: string; // Nuevo: Fondo detrás de la X (para el recorte)\n thickness?: string;\n color?: string;\n gap?: string;\n className?: string;\n}\n\nexport default function XSeparator({\n orientation = 'horizontal',\n variant = 'solid',\n isFaded = false,\n hasX = false,\n xColor, \n xBg = 'white',\n thickness = '1px',\n color = '#e2e8f0',\n gap = '1rem',\n className = ''\n}: XSeparatorProps) {\n \n const dynamicStyles = {\n '--separator-color': color,\n '--separator-thickness': thickness,\n '--separator-margin': gap,\n '--x-color': xColor || color, // Si no se define xColor, usa el color de la línea\n '--x-bg': xBg,\n } as React.CSSProperties;\n\n const classes = [\n styles.separator,\n orientation === 'vertical' ? styles.vertical : styles.horizontal,\n variant !== 'solid' && styles[variant],\n isFaded && styles.faded,\n ].filter(Boolean).join(' ');\n\n const line = <hr className={classes} style={dynamicStyles} />;\n\n if (!hasX) return line;\n\n return (\n <div className={`${styles.separatorContainer} ${className}`} style={dynamicStyles}>\n {line}\n <div className={styles.iconWrapper}>\n ✕\n </div>\n </div>\n );\n}","import React, { Children, HTMLAttributes, useEffect, useRef, useState, useCallback } from \"react\";\nimport styles from \"./XZigZagLayout.module.css\";\n\nexport type XZigZagLayoutProps = HTMLAttributes<HTMLDivElement> & {\n children: React.ReactNode;\n startSide?: \"left\" | \"right\";\n gap?: number | string;\n offset?: number | string;\n textAlign?: \"inherit\" | \"side\" | \"left\" | \"right\";\n showLine?: boolean;\n lineColor?: string;\n lineThickness?: number | string;\n};\n\nexport default function XZigZagLayout({\n children,\n className,\n style,\n startSide = \"left\",\n gap,\n offset,\n textAlign = \"inherit\",\n showLine = false,\n lineColor = \"#cccccc\",\n lineThickness = 2,\n ...rest\n}: XZigZagLayoutProps) {\n const items = Children.toArray(children).filter(Boolean);\n const containerRef = useRef<HTMLDivElement>(null);\n const itemsRef = useRef<(HTMLDivElement | null)[]>([]);\n const pathRef = useRef<SVGPathElement>(null);\n\n const [points, setPoints] = useState<{ x: number; y: number }[]>([]);\n const [pathLength, setPathLength] = useState(0);\n const [drawProgress, setDrawProgress] = useState(0);\n\n // Calcula el centro de cada elemento para dibujar los puntos\n const calculatePoints = useCallback(() => {\n if (!containerRef.current) return;\n const containerRect = containerRef.current.getBoundingClientRect();\n\n const newPoints = itemsRef.current.filter(Boolean).map((el) => {\n const rect = el!.getBoundingClientRect();\n return {\n x: rect.left + rect.width / 2 - containerRect.left,\n y: rect.top + rect.height / 2 - containerRect.top,\n };\n });\n\n if (newPoints.length > 0) {\n newPoints.unshift({ x: newPoints[0].x, y: 0 }); // Inicia arriba\n newPoints.push({ x: newPoints[newPoints.length - 1].x, y: containerRect.height }); // Termina abajo\n }\n\n setPoints(newPoints);\n }, []);\n\n useEffect(() => {\n if (!showLine || !containerRef.current) return;\n const observer = new ResizeObserver(() => calculatePoints());\n observer.observe(containerRef.current);\n calculatePoints();\n return () => observer.disconnect();\n }, [showLine, calculatePoints]);\n\n useEffect(() => {\n if (pathRef.current) setPathLength(pathRef.current.getTotalLength());\n }, [points]);\n\n useEffect(() => {\n if (!showLine) return;\n const handleScroll = () => {\n if (!containerRef.current) return;\n const { top, height } = containerRef.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n const start = windowHeight / 2;\n const progress = (start - top) / height;\n\n setDrawProgress(Math.min(Math.max(progress, 0), 1));\n };\n\n window.addEventListener(\"scroll\", handleScroll);\n handleScroll();\n return () => window.removeEventListener(\"scroll\", handleScroll);\n }, [showLine]);\n\n const cssVars: Record<string, string> = {};\n if (gap !== undefined) cssVars[\"--x-zigzag-gap\"] = typeof gap === \"number\" ? `${gap}px` : gap;\n if (offset !== undefined) cssVars[\"--x-zigzag-offset\"] = typeof offset === \"number\" ? `${offset}px` : offset;\n\n const mergedStyle: React.CSSProperties = { ...style, ...cssVars };\n\n const pathD = points.length > 0\n ? `M ${points[0].x} ${points[0].y} ` + points.slice(1).map((p) => `L ${p.x} ${p.y}`).join(\" \")\n : \"\";\n\n return (\n <div\n ref={containerRef}\n {...rest}\n className={[styles.layout, className].filter(Boolean).join(\" \")}\n style={mergedStyle}\n >\n {showLine && points.length > 0 && (\n <svg className={styles.svgLine} xmlns=\"http://www.w3.org/2000/svg\">\n <path\n ref={pathRef}\n d={pathD}\n fill=\"none\"\n stroke={lineColor}\n strokeWidth={lineThickness}\n strokeDasharray={pathLength}\n strokeDashoffset={pathLength - pathLength * drawProgress}\n style={{ transition: \"stroke-dashoffset 0.1s ease-out\" }}\n />\n </svg>\n )}\n\n {items.map((child, index) => {\n const isStartLeft = startSide === \"left\";\n const alignLeft = isStartLeft ? index % 2 === 0 : index % 2 !== 0;\n const alignmentClass =\n textAlign === \"side\"\n ? alignLeft ? styles.textLeft : styles.textRight\n : textAlign === \"left\" ? styles.textLeft : textAlign === \"right\" ? styles.textRight : \"\";\n\n return (\n <div key={index} className={`${styles.item} ${alignLeft ? styles.left : styles.right} ${alignmentClass}`}>\n {/* El wrapper interno nos permite medir exactamente dónde queda el contenido */}\n <div ref={(el) => { itemsRef.current[index] = el; }} className={styles.contentWrapper}>\n {child}\n </div>\n </div>\n );\n })}\n </div>\n );\n}",".layout {\n width: min(100%, 72rem);\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n gap: var(--x-zigzag-gap, 0.5rem);\n padding-inline: clamp(0.5rem, 2vw, 1rem);\n position: relative; \n}\n\n/* Nuevos estilos para el SVG de la línea */\n.svgLine {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 0;\n}\n\n.item {\n width: 100%;\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n}\n\n.item > * {\n width: 100%;\n text-align: inherit;\n}\n\n/* Wrapper transparente que envuelve al child */\n.contentWrapper {\n width: 100%;\n}\n\n.textLeft > * {\n text-align: left;\n}\n\n.textRight > * {\n text-align: right;\n}\n\n.left > * {\n grid-column: 2 / 8;\n}\n\n.right > * {\n grid-column: 6 / 12;\n}\n\n@media (max-width: 768px) {\n /* En lugar de ocupar las 12 columnas, los hacemos un poco más angostos para que sus centros se desfasen */\n .left > * {\n grid-column: 1 / 11;\n }\n\n .right > * {\n grid-column: 3 / 13;\n }\n}"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/content/xinteractivephrase/XInteractivePhrase.tsx","../src/components/content/xinteractivephrase/XInteractivePhrase.module.css"],"sourcesContent":["\"use client\";\n\nimport React, { useState, KeyboardEvent } from \"react\";\nimport styles from \"./XInteractivePhrase.module.css\";\n\nexport interface WordConfig {\n text: string;\n // Solo comportamientos de interacción\n type: \"normal\" | \"underline\" | \"button\" | \"blur1\" | \"blur2\"; \n breakAfter?: boolean;\n italic?: boolean; // Esto controla el <em>\n bold?: boolean; // Esto controla el <strong>\n}\n\nexport interface XInteractivePhraseProps {\n words: WordConfig[];\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"span\";\n className?: string;\n}\n\nexport default function XInteractivePhrase({ \n words, \n as: Tag = \"p\", \n className = \"\" \n}: XInteractivePhraseProps) {\n const [active1, setActive1] = useState<boolean>(false);\n const [active2, setActive2] = useState<boolean>(false);\n\n const handleAction = (type: \"underline\" | \"button\") => {\n if (type === \"underline\") setActive1(!active1);\n if (type === \"button\") setActive2(!active2);\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLSpanElement>, type: \"underline\" | \"button\") => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleAction(type);\n }\n };\n\n return (\n <div className={`${styles.container} ${className}`}>\n <Tag className={styles.title}>\n {words.map((word, index) => {\n let dynamicClass = \"\";\n let clickHandler: (() => void) | undefined = undefined;\n let keyHandler: ((e: KeyboardEvent<HTMLSpanElement>) => void) | undefined = undefined;\n\n // Gestión de lógica por tipo\n if (word.type === \"underline\") {\n dynamicClass = styles.underlineEffect;\n clickHandler = () => handleAction(\"underline\");\n keyHandler = (e) => onKeyDown(e, \"underline\");\n } \n else if (word.type === \"button\") {\n dynamicClass = styles.buttonEffect;\n clickHandler = () => handleAction(\"button\");\n keyHandler = (e) => onKeyDown(e, \"button\");\n } \n else if (word.type === \"blur1\") {\n dynamicClass = `${styles.blurEffect} ${active1 ? styles.isVisible : styles.isHidden}`;\n } \n else if (word.type === \"blur2\") {\n dynamicClass = `${styles.blurEffect} ${active2 ? styles.isVisible : styles.isHidden}`;\n }\n\n // Renderizado del contenido con estilos combinables\n let content: React.ReactNode = word.text;\n if (word.italic) content = <em>{content}</em>;\n if (word.bold) content = <strong>{content}</strong>;\n\n return (\n <React.Fragment key={index}>\n <span\n className={dynamicClass}\n onClick={clickHandler}\n onKeyDown={keyHandler}\n role={clickHandler ? \"button\" : undefined}\n tabIndex={clickHandler ? 0 : undefined}\n >\n {content}\n </span>\n {word.breakAfter ? <span className={styles.lineBreak} /> : \" \"}\n </React.Fragment>\n );\n })}\n </Tag>\n </div>\n );\n}",".container {\n padding: 1rem 0;\n color: var(--text, #000);\n width: 100%;\n}\n\n.title {\n margin: 0;\n padding: 0;\n line-height: 1.3;\n font-weight: inherit;\n text-align: inherit;\n}\n\n/* Escala tipográfica fluida */\nh1.title { font-size: clamp(2rem, 6vw, 2.2rem); font-weight: 800; margin: 0; padding: 0; text-align: inherit; }\nh2.title { font-size: clamp(1.675rem, 4vw, 1.8rem); font-weight: 700; margin: 0; padding: 0; text-align: inherit; }\nh3.title { font-size: clamp(1.4rem, 3vw, 1.95rem); font-weight: 700; margin: 0; padding: 0; text-align: inherit; }\nh4.title { font-size: clamp(1.25rem, 3vw, 2rem); font-weight: 600; margin: 0; padding: 0; text-align: inherit; }\nh5.title { font-size: clamp(1.125rem, 3vw, 1.5rem); font-weight: 600; margin: 0; padding: 0; text-align: inherit; }\nh6.title { font-size: clamp(1rem, 2.5vw, 1.25rem); font-weight: 600; margin: 0; padding: 0; text-align: inherit; }\np.title { font-size: 1rem; font-weight: 400; margin: 0; padding: 0; text-align: inherit; }\n\n/* Estilos para etiquetas de énfasis */\n.title strong {\n font-weight: 900;\n color: var(--accent, #0070f3);\n}\n\n.title em {\n font-style: italic;\n font-family: serif; /* Opcional: da un toque elegante a las itálicas */\n}\n\n/* Efectos */\n.underlineEffect {\n position: relative;\n cursor: pointer;\n color: var(--accent, #0070f3);\n display: inline-block;\n transition: color 0.3s ease;\n}\n\n.underlineEffect::after {\n content: \"\";\n position: absolute;\n bottom: -2px;\n left: 0;\n height: 0.15em;\n width: 100%;\n background: repeating-linear-gradient(\n 45deg,\n transparent,\n transparent 2px,\n currentColor 2px,\n currentColor 4px\n );\n transition: opacity 0.3s ease;\n}\n\n.underlineEffect:hover::after {\n opacity: 0;\n}\n\n.buttonEffect {\n display: inline-block;\n padding: 0.1em 0.6em;\n border: 2px dashed currentColor;\n border-radius: 9999px;\n cursor: pointer;\n color: var(--accent, #0070f3);\n transition: all 0.3s ease;\n}\n\n.buttonEffect:hover {\n background: currentColor;\n color: var(--bg, #fff);\n}\n\n.blurEffect {\n display: inline-block;\n transition: filter 0.7s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.7s ease;\n}\n\n.isVisible {\n filter: blur(0);\n opacity: 1;\n}\n\n.isHidden {\n filter: blur(10px);\n opacity: 0.3;\n user-select: none;\n}\n\n.lineBreak {\n display: block;\n height: 0.8rem;\n}\n\n.underlineEffect:focus-visible,\n.buttonEffect:focus-visible {\n outline: 2px solid var(--accent, #0070f3);\n outline-offset: 4px;\n}"],"mappings":";AAEA,OAAO,SAAS,gBAA+B;;;ACF/C;;;ADoEqC,cAIzB,YAJyB;AAhDtB,SAAR,mBAAoC;AAAA,EACzC;AAAA,EACA,IAAI,MAAM;AAAA,EACV,YAAY;AACd,GAA4B;AAC1B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,KAAK;AACrD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,KAAK;AAErD,QAAM,eAAe,CAAC,SAAiC;AACrD,QAAI,SAAS,YAAa,YAAW,CAAC,OAAO;AAC7C,QAAI,SAAS,SAAU,YAAW,CAAC,OAAO;AAAA,EAC5C;AAEA,QAAM,YAAY,CAAC,GAAmC,SAAiC;AACrF,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,QAAE,eAAe;AACjB,mBAAa,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,SACE,oBAAC,SAAI,WAAW,GAAG,2BAAO,SAAS,IAAI,SAAS,IAC9C,8BAAC,OAAI,WAAW,2BAAO,OACpB,gBAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,QAAI,eAAe;AACnB,QAAI,eAAyC;AAC7C,QAAI,aAAwE;AAG5E,QAAI,KAAK,SAAS,aAAa;AAC7B,qBAAe,2BAAO;AACtB,qBAAe,MAAM,aAAa,WAAW;AAC7C,mBAAa,CAAC,MAAM,UAAU,GAAG,WAAW;AAAA,IAC9C,WACS,KAAK,SAAS,UAAU;AAC/B,qBAAe,2BAAO;AACtB,qBAAe,MAAM,aAAa,QAAQ;AAC1C,mBAAa,CAAC,MAAM,UAAU,GAAG,QAAQ;AAAA,IAC3C,WACS,KAAK,SAAS,SAAS;AAC9B,qBAAe,GAAG,2BAAO,UAAU,IAAI,UAAU,2BAAO,YAAY,2BAAO,QAAQ;AAAA,IACrF,WACS,KAAK,SAAS,SAAS;AAC9B,qBAAe,GAAG,2BAAO,UAAU,IAAI,UAAU,2BAAO,YAAY,2BAAO,QAAQ;AAAA,IACrF;AAGA,QAAI,UAA2B,KAAK;AACpC,QAAI,KAAK,OAAQ,WAAU,oBAAC,QAAI,mBAAQ;AACxC,QAAI,KAAK,KAAM,WAAU,oBAAC,YAAQ,mBAAQ;AAE1C,WACE,qBAAC,MAAM,UAAN,EACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAW;AAAA,UACX,MAAM,eAAe,WAAW;AAAA,UAChC,UAAU,eAAe,IAAI;AAAA,UAE5B;AAAA;AAAA,MACH;AAAA,MACC,KAAK,aAAa,oBAAC,UAAK,WAAW,2BAAO,WAAW,IAAK;AAAA,SAVxC,KAWrB;AAAA,EAEJ,CAAC,GACH,GACF;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/navigation/xnavbar/XNavbar.tsx","../src/components/navigation/xnavbar/XNavbar.module.css"],"sourcesContent":["\"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":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/forms/xcontactform/XContactForm.tsx","../src/components/forms/xcontactform/XContactForm.module.css","../src/components/forms/xnewsletter/XNewsletter.tsx","../src/components/forms/xnewsletter/XNewsletter.module.css"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport styles from \"./XContactForm.module.css\";\n\ntype Status = { ok: boolean; msg: string } | null;\n\nexport interface XContactFormProps {\n // Visibilidad\n showName?: boolean;\n showEmail?: boolean;\n showPhone?: boolean;\n showSubject?: boolean;\n showMessage?: boolean;\n \n // Placeholders\n namePlaceholder?: string;\n emailPlaceholder?: string;\n phonePlaceholder?: string;\n subjectPlaceholder?: string;\n messagePlaceholder?: string;\n\n // Diseño\n labelColor?: string;\n wrapperBackgroundColor?: string;\n wrapperBorderColor?: string;\n wrapperBorderWidth?: string;\n wrapperBorderRadius?: \"rounded\" | \"square\";\n wrapperBorderStyle?: \"solid\" | \"dashed\" | \"dotted\";\n fieldBorderColor?: string;\n fieldBorderWidth?: string;\n fieldBorderRadius?: \"rounded\" | \"square\";\n fieldBorderStyle?: \"solid\" | \"dashed\" | \"dotted\";\n buttonColor?: string;\n buttonBorderColor?: string;\n buttonBorderWidth?: string;\n buttonBorderRadius?: \"rounded\" | \"square\";\n buttonBorderStyle?: \"solid\" | \"dashed\" | \"dotted\";\n buttonHoverColor?: string;\n buttonHoverTextColor?: string;\n buttonHoverBorderColor?: string;\n buttonTextColor?: string;\n buttonAlignment?: \"left\" | \"right\";\n\n // Mensajes de estado\n requiredFieldsMessage?: string;\n honeypotMessage?: string;\n submitSuccessMessage?: string;\n statusSuccessColor?: string;\n statusErrorColor?: string;\n\n // Decorativos\n decorativeX?: boolean;\n decorativeXColor?: string;\n\n size?: \"small\" | \"medium\" | \"large\";\n layout?: \"vertical\" | \"grid\";\n}\n\nexport default function XContactForm({\n showName = true,\n showEmail = true,\n showPhone = true,\n showSubject = true,\n showMessage = true,\n namePlaceholder = \"Tu nombre\",\n emailPlaceholder = \"tucorreo@ejemplo.com\",\n phonePlaceholder = \"+34 600 000 000\",\n subjectPlaceholder = \"Tema del mensaje\",\n messagePlaceholder = \"Cuéntame qué necesitas…\",\n labelColor,\n wrapperBackgroundColor,\n wrapperBorderColor,\n wrapperBorderWidth,\n wrapperBorderRadius = \"rounded\",\n wrapperBorderStyle = \"solid\",\n fieldBorderColor,\n fieldBorderWidth,\n fieldBorderRadius = \"rounded\",\n fieldBorderStyle = \"solid\",\n buttonColor,\n buttonBorderColor,\n buttonBorderWidth,\n buttonBorderRadius = \"rounded\",\n buttonBorderStyle = \"solid\",\n buttonHoverColor,\n buttonHoverTextColor,\n buttonHoverBorderColor,\n buttonTextColor,\n buttonAlignment = \"left\",\n requiredFieldsMessage = \"Rellena los campos obligatorios.\",\n honeypotMessage = \"Gracias.\",\n submitSuccessMessage = \"Abriendo tu aplicación de correo…\",\n statusSuccessColor,\n statusErrorColor,\n decorativeX = false,\n decorativeXColor = \"currentColor\",\n size = \"medium\",\n layout = \"grid\",\n}: XContactFormProps) {\n const [status, setStatus] = useState<Status>(null);\n\n function onSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setStatus(null);\n\n const form = e.currentTarget;\n const fd = new FormData(form);\n\n if ((fd.get(\"website\") as string)?.length) {\n setStatus({ ok: true, msg: honeypotMessage });\n form.reset();\n return;\n }\n\n const name = showName ? String(fd.get(\"name\") || \"\").trim() : \"\";\n const email = showEmail ? String(fd.get(\"email\") || \"\").trim() : \"\";\n const phone = showPhone ? String(fd.get(\"phone\") || \"\").trim() : \"\";\n const subject = showSubject\n ? String(fd.get(\"subject\") || \"Contacto desde web\").trim()\n : \"Contacto desde web\";\n const message = showMessage ? String(fd.get(\"message\") || \"\").trim() : \"\";\n\n if (\n (showName && !name) ||\n (showEmail && !email) ||\n (showPhone && !phone) ||\n (showMessage && !message)\n ) {\n setStatus({ ok: false, msg: requiredFieldsMessage });\n return;\n }\n\n const bodyLines = [];\n if (showName) bodyLines.push(`Nombre: ${name}`);\n if (showEmail) bodyLines.push(`Email: ${email}`);\n if (showPhone) bodyLines.push(`Teléfono: ${phone}`);\n bodyLines.push(\"\");\n if (showMessage) bodyLines.push(message);\n\n const body = bodyLines.join(\"\\n\");\n const to = \"x@xscriptor.com\";\n const mailto = `mailto:${encodeURIComponent(to)}?subject=${encodeURIComponent(\n subject\n )}&body=${encodeURIComponent(body)}`;\n\n window.location.href = mailto;\n setStatus({ ok: true, msg: submitSuccessMessage });\n }\n\n const radiusMap = {\n rounded: \"0.5rem\",\n square: \"0\",\n } as const;\n\n const alignmentMap = {\n left: \"flex-start\",\n right: \"flex-end\",\n } as const;\n\n // Variables CSS dinámicas para estilos configurables\n const customStyles = {\n ...(decorativeXColor && { \"--decorative-x-color\": decorativeXColor }),\n ...(labelColor && { \"--label-color\": labelColor }),\n ...(wrapperBackgroundColor && { \"--wrapper-bg-color\": wrapperBackgroundColor }),\n ...(wrapperBorderColor && { \"--wrapper-border-color\": wrapperBorderColor }),\n ...(wrapperBorderWidth && { \"--wrapper-border-width\": wrapperBorderWidth }),\n \"--wrapper-radius\": radiusMap[wrapperBorderRadius],\n \"--wrapper-border-style\": wrapperBorderStyle,\n ...(fieldBorderColor && { \"--field-border-color\": fieldBorderColor }),\n ...(fieldBorderWidth && { \"--field-border-width\": fieldBorderWidth }),\n \"--field-radius\": radiusMap[fieldBorderRadius],\n \"--field-border-style\": fieldBorderStyle,\n ...(buttonColor && { \"--btn-bg-color\": buttonColor }),\n ...(buttonBorderColor && { \"--btn-border-color\": buttonBorderColor }),\n ...(buttonBorderWidth && { \"--btn-border-width\": buttonBorderWidth }),\n \"--btn-radius\": radiusMap[buttonBorderRadius],\n \"--btn-border-style\": buttonBorderStyle,\n \"--btn-alignment\": alignmentMap[buttonAlignment],\n ...(buttonHoverColor && { \"--btn-hover-bg-color\": buttonHoverColor }),\n ...(buttonHoverTextColor && { \"--btn-hover-text-color\": buttonHoverTextColor }),\n ...(buttonHoverBorderColor && { \"--btn-hover-border-color\": buttonHoverBorderColor }),\n ...(buttonTextColor && { \"--btn-text-color\": buttonTextColor }),\n ...(statusSuccessColor && { \"--status-ok-color\": statusSuccessColor }),\n ...(statusErrorColor && { \"--status-error-color\": statusErrorColor }),\n } as React.CSSProperties;\n\n return (\n <div className={`${styles.wrapper} ${styles[size]} ${decorativeX ? styles.withDecorativeX : \"\"}`} style={customStyles}>\n {decorativeX && <div className={styles.decorativeXTop}>✕</div>}\n <form onSubmit={onSubmit} className={`${styles.form} ${styles[layout]}`} noValidate>\n <div className={styles.honeypot} aria-hidden=\"true\">\n <label htmlFor=\"website\">Tu web</label>\n <input id=\"website\" name=\"website\" type=\"text\" tabIndex={-1} autoComplete=\"off\" />\n </div>\n\n {(showName || showEmail || showPhone) && (\n <div className={styles.row}>\n {showName && (\n <div className={styles.field}>\n <label htmlFor=\"name\">Nombre</label>\n <input id=\"name\" name=\"name\" type=\"text\" placeholder={namePlaceholder} required maxLength={80} />\n </div>\n )}\n {showEmail && (\n <div className={styles.field}>\n <label htmlFor=\"email\">Email</label>\n <input id=\"email\" name=\"email\" type=\"email\" inputMode=\"email\" placeholder={emailPlaceholder} required />\n </div>\n )}\n {showPhone && (\n <div className={styles.field}>\n <label htmlFor=\"phone\">Teléfono</label>\n <input id=\"phone\" name=\"phone\" type=\"tel\" inputMode=\"tel\" placeholder={phonePlaceholder} required maxLength={20} />\n </div>\n )}\n </div>\n )}\n\n {showSubject && (\n <div className={styles.field}>\n <label htmlFor=\"subject\">Asunto</label>\n <input id=\"subject\" name=\"subject\" type=\"text\" placeholder={subjectPlaceholder} required maxLength={120} />\n </div>\n )}\n\n {showMessage && (\n <div className={styles.field}>\n <label htmlFor=\"message\">Mensaje</label>\n <textarea id=\"message\" name=\"message\" rows={6} placeholder={messagePlaceholder} required maxLength={3000} />\n </div>\n )}\n\n <div className={styles.buttoncontainer}>\n <button type=\"submit\" className={styles.button}>\n Enviar\n </button>\n </div>\n\n <p className={`${styles.status} ${status?.ok ? styles.statusOk : status === null ? \"\" : styles.statusError}`} role=\"status\" aria-live=\"polite\">\n {status?.msg}\n </p>\n </form>\n {decorativeX && <div className={styles.decorativeXBottom}>✕</div>}\n </div>\n );\n}","/* Tamaños dinámicos base */\n.wrapper {\n --input-padding: .65rem .9rem;\n --font-size: 16px;\n --form-gap: 1.25rem;\n --row-gap: .85rem;\n --field-gap: .45rem;\n --button-min-width: 140px;\n --label-color: inherit;\n --wrapper-bg-color: transparent;\n --wrapper-border-color: transparent;\n --wrapper-border-width: 0px;\n --wrapper-border-style: solid;\n --wrapper-radius: .5rem;\n --field-border-color: var(--border, #ccc);\n --field-border-width: 1px;\n --field-border-style: solid;\n --field-radius: .5rem;\n --btn-bg-color: var(--bg, #333);\n --btn-text-color: var(--text, #fff);\n --btn-border-color: transparent;\n --btn-border-width: 0px;\n --btn-border-style: solid;\n --btn-radius: .5rem;\n --btn-alignment: flex-start;\n --btn-hover-bg-color: var(--btn-bg-color);\n --btn-hover-text-color: var(--btn-text-color);\n --btn-hover-border-color: var(--btn-border-color);\n --status-ok-color: #1fa37a;\n --status-error-color: #d16a6a;\n \n max-width: 900px;\n margin: 0 auto;\n padding: 2rem 1rem;\n background-color: var(--wrapper-bg-color);\n border: var(--wrapper-border-width) var(--wrapper-border-style) var(--wrapper-border-color);\n border-radius: var(--wrapper-radius);\n}\n\n/* Modificadores de tamaño */\n.small {\n --input-padding: .35rem .55rem;\n --font-size: 13px;\n --form-gap: .75rem;\n --row-gap: .6rem;\n --field-gap: .3rem;\n --button-min-width: 118px;\n}\n.medium {\n --input-padding: .5rem .7rem;\n --font-size: 15px;\n --form-gap: 1rem;\n --row-gap: .7rem;\n --field-gap: .4rem;\n --button-min-width: 130px;\n}\n.large {\n --input-padding: 1rem 1.2rem;\n --font-size: 18px;\n --form-gap: 1.5rem;\n --row-gap: 1rem;\n --field-gap: .5rem;\n --button-min-width: 150px;\n}\n\n.form {\n display: grid;\n gap: var(--form-gap);\n max-width: 100%;\n}\n\n/* Layouts */\n.row {\n display: grid;\n gap: var(--row-gap);\n}\n\n.grid .row {\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n}\n\n.vertical .row {\n grid-template-columns: 1fr;\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: var(--field-gap);\n}\n\n.field label {\n font-size: calc(var(--font-size) - 2px);\n font-weight: 500;\n color: var(--label-color);\n}\n\n.field input,\n.field textarea {\n width: 100%;\n padding: var(--input-padding);\n border: var(--field-border-width) var(--field-border-style) var(--field-border-color);\n border-radius: var(--field-radius);\n font-size: var(--font-size);\n box-sizing: border-box;\n font-family: inherit;\n}\n\n.field input::placeholder,\n.field textarea::placeholder {\n color: #888;\n}\n\n.buttoncontainer {\n display: flex;\n justify-content: var(--btn-alignment);\n margin-top: 0.25rem;\n}\n\n.button {\n padding: var(--input-padding);\n border-radius: var(--btn-radius);\n border: var(--btn-border-width) var(--btn-border-style) var(--btn-border-color);\n background-color: var(--btn-bg-color);\n color: var(--btn-text-color);\n cursor: pointer;\n font-size: var(--font-size);\n font-weight: 600;\n min-width: var(--button-min-width);\n transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, opacity 0.2s ease;\n}\n\n.button:hover {\n background-color: var(--btn-hover-bg-color);\n color: var(--btn-hover-text-color);\n border-color: var(--btn-hover-border-color);\n opacity: 0.95;\n}\n\n.status {\n min-height: 1.5rem;\n font-size: calc(var(--font-size) - 2px);\n margin-top: 0.25rem;\n}\n\n.statusOk { color: var(--status-ok-color); }\n.statusError { color: var(--status-error-color); }\n\n.honeypot {\n position: absolute;\n left: -9999px;\n top: -9999px;\n}\n\n.withDecorativeX {\n position: relative;\n padding-top: 2.5rem;\n padding-bottom: 2.5rem;\n}\n\n.decorativeXTop,\n.decorativeXBottom {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n font-size: 0.5rem;\n font-weight: 300;\n color: var(--decorative-x-color, currentColor);\n opacity: 1;\n pointer-events: none;\n background-color: var(--wrapper-bg-color, transparent);\n padding: 0 0.3rem;\n line-height: 1;\n z-index: 1;\n}\n\n.decorativeXTop {\n top: 0;\n transform: translate(-50%, -50%);\n}\n\n.decorativeXBottom {\n bottom: 0;\n transform: translate(-50%, 50%);\n}","\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport styles from \"./XNewsletter.module.css\";\n\nexport interface XNewsletterProps {\n title?: string;\n placeholder?: string;\n buttonText?: string;\n termsText?: string;\n termsLinkText?: string;\n successMessage?: string;\n errorMessage?: string;\n termsErrorMessage?: string;\n termsLink?: string;\n apiRoute: string;\n method?: \"POST\" | \"GET\" | \"PUT\";\n payloadType?: \"formData\" | \"json\";\n layout?: \"horizontal\" | \"vertical\";\n accentColor?: string;\n textColor?: string;\n borderColor?: string;\n buttonTextColor?: string;\n containerClassName?: string; // Para clases extra desde afuera si las necesitas\n}\n\nexport default function XNewsletter({\n title = \"Recibe poesía y reflexiones\",\n placeholder = \"tu@email.com\",\n buttonText = \"Suscribirse\",\n termsText = \"Acepto\",\n termsLinkText = \"términos\",\n successMessage = \"¡Bienvenido(a)!\",\n errorMessage = \"Algo salió mal. Por favor, intenta de nuevo.\",\n termsErrorMessage = \"Debes aceptar los términos y condiciones para suscribirte...\",\n termsLink = \"/terminos-y-condiciones\",\n apiRoute,\n method = \"POST\",\n payloadType = \"formData\",\n layout = \"horizontal\",\n accentColor = \"var(--accent)\",\n textColor = \"var(--text)\",\n borderColor = \"var(--border)\",\n buttonTextColor = \"var(--accent-text)\",\n containerClassName = \"w-full max-w-4xl mx-auto px-4 py-6\",\n}: XNewsletterProps) {\n const [email, setEmail] = useState(\"\");\n const [acceptedTerms, setAcceptedTerms] = useState(false);\n const [message, setMessage] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setMessage(\"\");\n\n if (!acceptedTerms) {\n setMessage(termsErrorMessage);\n return;\n }\n\n setIsLoading(true);\n\n try {\n let bodyData: BodyInit | null | undefined = null;\n let headers: HeadersInit = {};\n\n if (payloadType === \"formData\") {\n const formData = new FormData();\n formData.append(\"email\", email);\n bodyData = formData;\n } else if (payloadType === \"json\") {\n bodyData = JSON.stringify({ email });\n headers = { \"Content-Type\": \"application/json\" };\n }\n\n const response = await fetch(apiRoute, {\n method,\n headers,\n body: method !== \"GET\" ? bodyData : undefined,\n cache: \"no-store\",\n });\n\n const data = await response.json();\n\n if (response.ok && data.success) {\n setMessage(data.message || successMessage);\n setEmail(\"\");\n setAcceptedTerms(false);\n } else {\n setMessage(data.error || errorMessage);\n }\n } catch {\n setMessage(errorMessage);\n } finally {\n setIsLoading(false);\n }\n };\n\n // Convertimos las props de colores a Variables CSS nativas.\n const customCssVariables = {\n \"--nws-accent\": accentColor,\n \"--nws-text\": textColor,\n \"--nws-border\": borderColor,\n \"--nws-btn-text\": buttonTextColor,\n } as React.CSSProperties;\n\n return (\n <div\n className={`${styles.container} ${containerClassName}`}\n style={customCssVariables}\n >\n <form\n onSubmit={handleSubmit}\n className={`${styles.form} ${styles[layout]}`}\n >\n {/* Título */}\n {title && <span className={styles.title}>{title}</span>}\n\n {/* Input */}\n <input\n type=\"email\"\n placeholder={placeholder}\n className={styles.input}\n aria-label=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n required\n disabled={isLoading}\n />\n\n {/* Grupo Acciones (Checkbox + Botón) */}\n <div\n className={`${styles.actions} ${\n layout === \"horizontal\"\n ? styles.actionsHorizontal\n : styles.actionsVertical\n }`}\n >\n {/* Checkbox */}\n <label className={styles.checkboxLabel}>\n <input\n type=\"checkbox\"\n className={styles.checkbox}\n checked={acceptedTerms}\n onChange={(e) => setAcceptedTerms(e.target.checked)}\n required\n disabled={isLoading}\n />\n <span>\n {termsText}{\" \"}\n <Link\n href={termsLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={styles.termsLink}\n >\n {termsLinkText}\n </Link>\n </span>\n </label>\n\n {/* Botón */}\n <button\n type=\"submit\"\n disabled={isLoading}\n className={styles.button}\n >\n {isLoading ? \"Enviando...\" : buttonText}\n </button>\n </div>\n </form>\n\n {/* Mensaje */}\n {message && (\n <p\n className={`${styles.message} ${\n layout === \"horizontal\"\n ? styles.messageHorizontal\n : styles.messageVertical\n }`}\n >\n {message}\n </p>\n )}\n </div>\n );\n}","/* XNewsletter.module.css */\n\n.container {\n /* Estas variables recibirán sus valores desde React */\n --nws-accent: var(--accent);\n --nws-text: var(--text);\n --nws-border: var(--border);\n --nws-btn-text: var(--accent-text);\n \n width: 100%;\n font-family: \"EB Garamond\", serif;\n}\n\n/* --- Layouts Base --- */\n.form {\n display: flex;\n gap: 1rem;\n}\n\n.horizontal {\n flex-direction: column;\n align-items: center;\n justify-content: center;\n}\n\n@media (min-width: 768px) {\n .horizontal {\n flex-direction: row;\n }\n}\n\n.vertical {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n max-width: 24rem; /* equivalente a max-w-sm */\n margin: 0 auto;\n}\n\n/* --- Elementos --- */\n.title {\n font-size: 0.875rem;\n white-space: nowrap;\n font-weight: 500;\n color: var(--nws-text);\n}\n\n.input {\n width: 100%;\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n border-radius: 0.5rem;\n border: 1px solid var(--nws-border);\n background-color: transparent;\n outline: none;\n transition: border-color 0.2s ease;\n color: var(--nws-text);\n caret-color: var(--nws-accent);\n font-family: inherit;\n}\n\n.horizontal .input {\n /* En escritorio, el input horizontal es de tamaño fijo (md:w-64) */\n}\n@media (min-width: 768px) {\n .horizontal .input {\n width: 16rem; \n }\n}\n\n.input:focus {\n border-color: var(--nws-accent);\n}\n\n/* --- Checkbox y Botón --- */\n.actions {\n display: flex;\n gap: 1rem;\n}\n\n.actionsHorizontal {\n flex-direction: row;\n align-items: center;\n}\n\n.actionsVertical {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n}\n\n.checkboxLabel {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.75rem;\n white-space: nowrap;\n cursor: pointer;\n color: var(--nws-text);\n}\n\n.checkboxLabel span {\n opacity: 0.7;\n}\n\n.checkbox {\n height: 0.875rem;\n width: 0.875rem;\n border-radius: 0.125rem;\n cursor: pointer;\n accent-color: var(--nws-accent);\n}\n\n.termsLink {\n text-decoration: underline;\n color: var(--nws-accent);\n transition: opacity 0.2s ease;\n}\n\n.termsLink:hover {\n opacity: 1;\n}\n\n.button {\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n border-radius: 0.5rem;\n border: 1px solid var(--nws-accent);\n color: var(--nws-accent);\n background-color: transparent;\n transition: all 0.2s ease;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.button:hover:not(:disabled) {\n background-color: var(--nws-accent);\n color: var(--nws-btn-text);\n}\n\n.button:disabled, .input:disabled, .checkbox:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.actionsVertical .button {\n width: 100%;\n}\n\n/* --- Feedback Message --- */\n.message {\n margin-top: 0.75rem;\n font-size: 0.75rem;\n color: var(--nws-accent);\n}\n\n.messageHorizontal {\n text-align: center;\n}\n\n.messageVertical {\n text-align: left;\n}"],"mappings":";AAEA,SAAS,gBAAgB;;;ACFzB;;;AD6LsB,cAEd,YAFc;AAlIP,SAAR,aAA8B;AAAA,EACnC,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB;AAAA,EACA;AAAA,EACA,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,OAAO;AAAA,EACP,SAAS;AACX,GAAsB;AACpB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAiB,IAAI;AAEjD,WAAS,SAAS,GAAqC;AACrD,MAAE,eAAe;AACjB,cAAU,IAAI;AAEd,UAAM,OAAO,EAAE;AACf,UAAM,KAAK,IAAI,SAAS,IAAI;AAE5B,QAAK,GAAG,IAAI,SAAS,GAAc,QAAQ;AACzC,gBAAU,EAAE,IAAI,MAAM,KAAK,gBAAgB,CAAC;AAC5C,WAAK,MAAM;AACX;AAAA,IACF;AAEA,UAAM,OAAO,WAAW,OAAO,GAAG,IAAI,MAAM,KAAK,EAAE,EAAE,KAAK,IAAI;AAC9D,UAAM,QAAQ,YAAY,OAAO,GAAG,IAAI,OAAO,KAAK,EAAE,EAAE,KAAK,IAAI;AACjE,UAAM,QAAQ,YAAY,OAAO,GAAG,IAAI,OAAO,KAAK,EAAE,EAAE,KAAK,IAAI;AACjE,UAAM,UAAU,cACZ,OAAO,GAAG,IAAI,SAAS,KAAK,oBAAoB,EAAE,KAAK,IACvD;AACJ,UAAM,UAAU,cAAc,OAAO,GAAG,IAAI,SAAS,KAAK,EAAE,EAAE,KAAK,IAAI;AAEvE,QACG,YAAY,CAAC,QACb,aAAa,CAAC,SACd,aAAa,CAAC,SACd,eAAe,CAAC,SACjB;AACA,gBAAU,EAAE,IAAI,OAAO,KAAK,sBAAsB,CAAC;AACnD;AAAA,IACF;AAEA,UAAM,YAAY,CAAC;AACnB,QAAI,SAAU,WAAU,KAAK,WAAW,IAAI,EAAE;AAC9C,QAAI,UAAW,WAAU,KAAK,UAAU,KAAK,EAAE;AAC/C,QAAI,UAAW,WAAU,KAAK,gBAAa,KAAK,EAAE;AAClD,cAAU,KAAK,EAAE;AACjB,QAAI,YAAa,WAAU,KAAK,OAAO;AAEvC,UAAM,OAAO,UAAU,KAAK,IAAI;AAChC,UAAM,KAAK;AACX,UAAM,SAAS,UAAU,mBAAmB,EAAE,CAAC,YAAY;AAAA,MACzD;AAAA,IACF,CAAC,SAAS,mBAAmB,IAAI,CAAC;AAElC,WAAO,SAAS,OAAO;AACvB,cAAU,EAAE,IAAI,MAAM,KAAK,qBAAqB,CAAC;AAAA,EACnD;AAEA,QAAM,YAAY;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,QAAM,eAAe;AAAA,IACnB,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAGA,QAAM,eAAe;AAAA,IACnB,GAAI,oBAAoB,EAAE,wBAAwB,iBAAiB;AAAA,IACnE,GAAI,cAAc,EAAE,iBAAiB,WAAW;AAAA,IAChD,GAAI,0BAA0B,EAAE,sBAAsB,uBAAuB;AAAA,IAC7E,GAAI,sBAAsB,EAAE,0BAA0B,mBAAmB;AAAA,IACzE,GAAI,sBAAsB,EAAE,0BAA0B,mBAAmB;AAAA,IACzE,oBAAoB,UAAU,mBAAmB;AAAA,IACjD,0BAA0B;AAAA,IAC1B,GAAI,oBAAoB,EAAE,wBAAwB,iBAAiB;AAAA,IACnE,GAAI,oBAAoB,EAAE,wBAAwB,iBAAiB;AAAA,IACnE,kBAAkB,UAAU,iBAAiB;AAAA,IAC7C,wBAAwB;AAAA,IACxB,GAAI,eAAe,EAAE,kBAAkB,YAAY;AAAA,IACnD,GAAI,qBAAqB,EAAE,sBAAsB,kBAAkB;AAAA,IACnE,GAAI,qBAAqB,EAAE,sBAAsB,kBAAkB;AAAA,IACnE,gBAAgB,UAAU,kBAAkB;AAAA,IAC5C,sBAAsB;AAAA,IACtB,mBAAmB,aAAa,eAAe;AAAA,IAC/C,GAAI,oBAAoB,EAAE,wBAAwB,iBAAiB;AAAA,IACnE,GAAI,wBAAwB,EAAE,0BAA0B,qBAAqB;AAAA,IAC7E,GAAI,0BAA0B,EAAE,4BAA4B,uBAAuB;AAAA,IACnF,GAAI,mBAAmB,EAAE,oBAAoB,gBAAgB;AAAA,IAC7D,GAAI,sBAAsB,EAAE,qBAAqB,mBAAmB;AAAA,IACpE,GAAI,oBAAoB,EAAE,wBAAwB,iBAAiB;AAAA,EACrE;AAEA,SACE,qBAAC,SAAI,WAAW,GAAG,qBAAO,OAAO,IAAI,qBAAO,IAAI,CAAC,IAAI,cAAc,qBAAO,kBAAkB,EAAE,IAAI,OAAO,cACtG;AAAA,mBAAe,oBAAC,SAAI,WAAW,qBAAO,gBAAgB,oBAAC;AAAA,IACxD,qBAAC,UAAK,UAAoB,WAAW,GAAG,qBAAO,IAAI,IAAI,qBAAO,MAAM,CAAC,IAAI,YAAU,MACjF;AAAA,2BAAC,SAAI,WAAW,qBAAO,UAAU,eAAY,QAC3C;AAAA,4BAAC,WAAM,SAAQ,WAAU,oBAAM;AAAA,QAC/B,oBAAC,WAAM,IAAG,WAAU,MAAK,WAAU,MAAK,QAAO,UAAU,IAAI,cAAa,OAAM;AAAA,SAClF;AAAA,OAEE,YAAY,aAAa,cACzB,qBAAC,SAAI,WAAW,qBAAO,KACpB;AAAA,oBACC,qBAAC,SAAI,WAAW,qBAAO,OACrB;AAAA,8BAAC,WAAM,SAAQ,QAAO,oBAAM;AAAA,UAC5B,oBAAC,WAAM,IAAG,QAAO,MAAK,QAAO,MAAK,QAAO,aAAa,iBAAiB,UAAQ,MAAC,WAAW,IAAI;AAAA,WACjG;AAAA,QAED,aACC,qBAAC,SAAI,WAAW,qBAAO,OACrB;AAAA,8BAAC,WAAM,SAAQ,SAAQ,mBAAK;AAAA,UAC5B,oBAAC,WAAM,IAAG,SAAQ,MAAK,SAAQ,MAAK,SAAQ,WAAU,SAAQ,aAAa,kBAAkB,UAAQ,MAAC;AAAA,WACxG;AAAA,QAED,aACC,qBAAC,SAAI,WAAW,qBAAO,OACrB;AAAA,8BAAC,WAAM,SAAQ,SAAQ,yBAAQ;AAAA,UAC/B,oBAAC,WAAM,IAAG,SAAQ,MAAK,SAAQ,MAAK,OAAM,WAAU,OAAM,aAAa,kBAAkB,UAAQ,MAAC,WAAW,IAAI;AAAA,WACnH;AAAA,SAEJ;AAAA,MAGD,eACC,qBAAC,SAAI,WAAW,qBAAO,OACrB;AAAA,4BAAC,WAAM,SAAQ,WAAU,oBAAM;AAAA,QAC/B,oBAAC,WAAM,IAAG,WAAU,MAAK,WAAU,MAAK,QAAO,aAAa,oBAAoB,UAAQ,MAAC,WAAW,KAAK;AAAA,SAC3G;AAAA,MAGD,eACC,qBAAC,SAAI,WAAW,qBAAO,OACrB;AAAA,4BAAC,WAAM,SAAQ,WAAU,qBAAO;AAAA,QAChC,oBAAC,cAAS,IAAG,WAAU,MAAK,WAAU,MAAM,GAAG,aAAa,oBAAoB,UAAQ,MAAC,WAAW,KAAM;AAAA,SAC5G;AAAA,MAGF,oBAAC,SAAI,WAAW,qBAAO,iBACrB,8BAAC,YAAO,MAAK,UAAS,WAAW,qBAAO,QAAQ,oBAEhD,GACF;AAAA,MAEA,oBAAC,OAAE,WAAW,GAAG,qBAAO,MAAM,IAAI,QAAQ,KAAK,qBAAO,WAAW,WAAW,OAAO,KAAK,qBAAO,WAAW,IAAI,MAAK,UAAS,aAAU,UACnI,kBAAQ,KACX;AAAA,OACF;AAAA,IACC,eAAe,oBAAC,SAAI,WAAW,qBAAO,mBAAmB,oBAAC;AAAA,KAC7D;AAEJ;;;AEpPA,SAAS,YAAAA,iBAAgB;AACzB,OAAO,UAAU;;;ACHjB;;;ADqHkB,gBAAAC,MAgCN,QAAAC,aAhCM;AA1FH,SAAR,YAA6B;AAAA,EAClC,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,YAAY;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,EACT,cAAc;AAAA,EACd,SAAS;AAAA,EACT,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,qBAAqB;AACvB,GAAqB;AACnB,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,EAAE;AACrC,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAAS,KAAK;AACxD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,EAAE;AACzC,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAEhD,QAAM,eAAe,OAAO,MAAuB;AACjD,MAAE,eAAe;AACjB,eAAW,EAAE;AAEb,QAAI,CAAC,eAAe;AAClB,iBAAW,iBAAiB;AAC5B;AAAA,IACF;AAEA,iBAAa,IAAI;AAEjB,QAAI;AACF,UAAI,WAAwC;AAC5C,UAAI,UAAuB,CAAC;AAE5B,UAAI,gBAAgB,YAAY;AAC9B,cAAM,WAAW,IAAI,SAAS;AAC9B,iBAAS,OAAO,SAAS,KAAK;AAC9B,mBAAW;AAAA,MACb,WAAW,gBAAgB,QAAQ;AACjC,mBAAW,KAAK,UAAU,EAAE,MAAM,CAAC;AACnC,kBAAU,EAAE,gBAAgB,mBAAmB;AAAA,MACjD;AAEA,YAAM,WAAW,MAAM,MAAM,UAAU;AAAA,QACrC;AAAA,QACA;AAAA,QACA,MAAM,WAAW,QAAQ,WAAW;AAAA,QACpC,OAAO;AAAA,MACT,CAAC;AAED,YAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,UAAI,SAAS,MAAM,KAAK,SAAS;AAC/B,mBAAW,KAAK,WAAW,cAAc;AACzC,iBAAS,EAAE;AACX,yBAAiB,KAAK;AAAA,MACxB,OAAO;AACL,mBAAW,KAAK,SAAS,YAAY;AAAA,MACvC;AAAA,IACF,QAAQ;AACN,iBAAW,YAAY;AAAA,IACzB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,qBAAqB;AAAA,IACzB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,EACpB;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,oBAAO,SAAS,IAAI,kBAAkB;AAAA,MACpD,OAAO;AAAA,MAEP;AAAA,wBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,WAAW,GAAG,oBAAO,IAAI,IAAI,oBAAO,MAAM,CAAC;AAAA,YAG1C;AAAA,uBAAS,gBAAAD,KAAC,UAAK,WAAW,oBAAO,OAAQ,iBAAM;AAAA,cAGhD,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL;AAAA,kBACA,WAAW,oBAAO;AAAA,kBAClB,cAAW;AAAA,kBACX,OAAO;AAAA,kBACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,kBACxC,UAAQ;AAAA,kBACR,UAAU;AAAA;AAAA,cACZ;AAAA,cAGA,gBAAAC;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,GAAG,oBAAO,OAAO,IAC1B,WAAW,eACP,oBAAO,oBACP,oBAAO,eACb;AAAA,kBAGA;AAAA,oCAAAA,MAAC,WAAM,WAAW,oBAAO,eACvB;AAAA,sCAAAD;AAAA,wBAAC;AAAA;AAAA,0BACC,MAAK;AAAA,0BACL,WAAW,oBAAO;AAAA,0BAClB,SAAS;AAAA,0BACT,UAAU,CAAC,MAAM,iBAAiB,EAAE,OAAO,OAAO;AAAA,0BAClD,UAAQ;AAAA,0BACR,UAAU;AAAA;AAAA,sBACZ;AAAA,sBACA,gBAAAC,MAAC,UACE;AAAA;AAAA,wBAAW;AAAA,wBACZ,gBAAAD;AAAA,0BAAC;AAAA;AAAA,4BACC,MAAM;AAAA,4BACN,QAAO;AAAA,4BACP,KAAI;AAAA,4BACJ,WAAW,oBAAO;AAAA,4BAEjB;AAAA;AAAA,wBACH;AAAA,yBACF;AAAA,uBACF;AAAA,oBAGA,gBAAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,UAAU;AAAA,wBACV,WAAW,oBAAO;AAAA,wBAEjB,sBAAY,gBAAgB;AAAA;AAAA,oBAC/B;AAAA;AAAA;AAAA,cACF;AAAA;AAAA;AAAA,QACF;AAAA,QAGC,WACC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,GAAG,oBAAO,OAAO,IAC1B,WAAW,eACP,oBAAO,oBACP,oBAAO,eACb;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":["useState","jsx","jsxs","useState"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/social/xsocialcontact/XSocialContact.module.css","../src/components/social/xsocialcontact/XSocialContact.tsx","../src/components/social/xsocialcontact/XSocialIcons.tsx"],"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","\"use client\";\n\nimport React from \"react\";\nimport styles from \"./XSocialContact.module.css\";\n\nexport interface SocialItem {\n id: string;\n href: string;\n label: string;\n icon: React.ReactNode;\n text?: string;\n iconColor?: string;\n iconHoverColor?: string;\n}\n\nexport interface XSocialContactProps {\n items: SocialItem[];\n columns?: number;\n rows?: number;\n size?: \"small\" | \"medium\" | \"large\";\n alignment?: \"left\" | \"center\" | \"right\";\n gap?: string;\n backgroundColor?: string;\n iconDefaultColor?: string;\n iconDefaultHoverColor?: string;\n borderColor?: string;\n borderWidth?: string;\n borderStyle?: \"solid\" | \"dashed\" | \"dotted\";\n borderRadius?: \"rounded\" | \"square\";\n padding?: string;\n textAlign?: \"left\" | \"center\" | \"right\";\n textColor?: string;\n textSize?: string;\n}\n\nexport default function XSocialContact({\n items,\n columns = 3,\n rows,\n size = \"medium\",\n alignment = \"center\",\n gap,\n backgroundColor,\n iconDefaultColor,\n iconDefaultHoverColor,\n borderColor,\n borderWidth,\n borderStyle = \"solid\",\n borderRadius = \"rounded\",\n padding,\n textAlign = \"center\",\n textColor,\n textSize,\n}: XSocialContactProps) {\n const sizeMap = {\n small: \"1rem\",\n medium: \"1.5rem\",\n large: \"2rem\",\n } as const;\n\n const alignmentMap = {\n left: \"flex-start\",\n center: \"center\",\n right: \"flex-end\",\n } as const;\n\n const textAlignMap = {\n left: \"left\",\n center: \"center\",\n right: \"right\",\n } as const;\n\n const radiusMap = {\n rounded: \"0.5rem\",\n square: \"0\",\n } as const;\n\n const defaultGap = gap || (size === \"small\" ? \"1rem\" : size === \"medium\" ? \"1.5rem\" : \"2rem\");\n const defaultPadding =\n padding || (size === \"small\" ? \"1rem\" : size === \"medium\" ? \"1.5rem\" : \"2rem\");\n const defaultTextSize = textSize || (size === \"small\" ? \"0.875rem\" : size === \"medium\" ? \"1rem\" : \"1.125rem\");\n\n const customStyles = {\n \"--columns\": columns.toString(),\n \"--gap\": defaultGap,\n \"--padding\": defaultPadding,\n \"--text-size\": defaultTextSize,\n \"--alignment\": alignmentMap[alignment],\n \"--text-align\": textAlignMap[textAlign],\n \"--icon-gap\": sizeMap[size],\n \"--border-radius\": radiusMap[borderRadius],\n ...(backgroundColor && { \"--bg-color\": backgroundColor }),\n ...(iconDefaultColor && { \"--icon-color\": iconDefaultColor }),\n ...(iconDefaultHoverColor && { \"--icon-hover-color\": iconDefaultHoverColor }),\n ...(borderColor && { \"--border-color\": borderColor }),\n ...(borderWidth && { \"--border-width\": borderWidth }),\n ...(textColor && { \"--text-color\": textColor }),\n \"--border-style\": borderStyle,\n } as React.CSSProperties;\n\n let containerClass = styles.container;\n if (rows) {\n containerClass += ` ${styles[`rows${rows}`]}`;\n }\n\n return (\n <div\n className={`${containerClass} ${styles[size]}`}\n style={customStyles}\n >\n {items.map((item) => (\n <a\n key={item.id}\n href={item.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={styles.item}\n title={item.label}\n style={{\n ...(item.iconColor && { \"--item-icon-color\": item.iconColor }),\n ...(item.iconHoverColor && { \"--item-icon-hover-color\": item.iconHoverColor }),\n } as React.CSSProperties}\n >\n <div className={styles.iconWrapper}>{item.icon}</div>\n {item.text && <span className={styles.text}>{item.text}</span>}\n </a>\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport React, { useState } from \"react\";\n\nexport interface XSocialIconProps extends Omit<React.SVGProps<SVGSVGElement>, \"color\" | \"children\"> {\n size?: number | string;\n color?: string;\n hoverColor?: string;\n fillColor?: string;\n hoverFillColor?: string;\n backgroundColor?: string;\n badgeColor?: string;\n badgeBackgroundColor?: string;\n strokeWidth?: number;\n showBadge?: boolean;\n title?: string;\n}\n\ntype IconPalette = {\n stroke: string;\n fill: string;\n badgeStroke: string;\n badgeFill: string;\n};\n\ntype SocialIconContentProps = {\n palette: IconPalette;\n};\n\ntype SocialIconRenderer = (props: SocialIconContentProps) => React.ReactNode;\n\nfunction XSocialIconShell({\n size = 24,\n color = \"currentColor\",\n hoverColor,\n fillColor,\n hoverFillColor,\n backgroundColor,\n badgeColor,\n badgeBackgroundColor,\n strokeWidth = 1.8,\n showBadge = true,\n title,\n style,\n children,\n ...rest\n}: XSocialIconProps & { children: SocialIconRenderer }) {\n const [isHovered, setIsHovered] = useState(false);\n\n const stroke = isHovered && hoverColor ? hoverColor : color;\n const fill = isHovered && hoverFillColor ? hoverFillColor : fillColor || stroke;\n const badgeStroke = badgeColor || stroke;\n const badgeFill = badgeBackgroundColor || \"transparent\";\n\n const palette = {\n stroke,\n fill,\n badgeStroke,\n badgeFill,\n };\n\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n role={title ? \"img\" : \"presentation\"}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n onPointerEnter={() => setIsHovered(true)}\n onPointerLeave={() => setIsHovered(false)}\n style={{ color: stroke, ...(style ?? {}) }}\n {...rest}\n >\n {title ? <title>{title}</title> : null}\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10.5\"\n fill={backgroundColor || \"none\"}\n stroke={backgroundColor ? \"none\" : stroke}\n strokeOpacity={backgroundColor ? undefined : 0.14}\n strokeWidth={backgroundColor ? undefined : strokeWidth}\n />\n {children({ palette })}\n {showBadge && (\n <g>\n <circle cx=\"18\" cy=\"18\" r=\"2.6\" fill={badgeFill} stroke={badgeStroke} strokeWidth=\"1\" />\n <path d=\"M17.05 17.05L18.95 18.95M18.95 17.05L17.05 18.95\" stroke={badgeStroke} strokeWidth=\"1.15\" strokeLinecap=\"round\" />\n </g>\n )}\n </svg>\n );\n}\n\nexport function XTelegramIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.8}>\n {({ palette }) => (\n <>\n <path\n d=\"M9.2 12.4l2.15 2.15 5.1-5.1M20.6 4.2L4 12l6.45 1.8 1.8 6.45 2.55-4.2 4.2 2.55 1.6-14.4z\"\n stroke={palette.stroke}\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n <circle cx=\"12\" cy=\"12\" r=\"9.75\" fill=\"none\" stroke={palette.stroke} strokeOpacity=\"0.18\" strokeWidth=\"1\" />\n </>\n )}\n </XSocialIconShell>\n );\n}\n\nexport function XInstagramIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.6}>\n {({ palette }) => (\n <>\n <rect x=\"6.2\" y=\"6.2\" width=\"11.6\" height=\"11.6\" rx=\"3.2\" ry=\"3.2\" stroke={palette.stroke} strokeWidth=\"1.6\" fill=\"none\" />\n <circle cx=\"12\" cy=\"12\" r=\"3.15\" stroke={palette.stroke} strokeWidth=\"1.6\" fill=\"none\" />\n <circle cx=\"16.3\" cy=\"7.7\" r=\"0.7\" fill={palette.fill} />\n </>\n )}\n </XSocialIconShell>\n );\n}\n\nexport function XWhatsappIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.5}>\n {({ palette }) => (\n <>\n <path\n d=\"M16.72 13.06c-.29-.15-1.71-.84-1.98-.94-.26-.1-.45-.15-.64.14-.19.29-.74.94-.9 1.13-.16.19-.33.22-.62.08-.29-.15-1.23-.45-2.35-1.45-.87-.77-1.45-1.72-1.62-2.01-.16-.29-.02-.45.12-.59.13-.13.29-.33.43-.49.14-.16.18-.28.27-.47.09-.19.04-.36-.02-.51-.07-.15-.64-1.54-.88-2.1-.23-.55-.47-.48-.64-.49-.16-.01-.36-.01-.55-.01-.19 0-.5.07-.76.36-.26.29-1 1.01-1 2.47 0 1.45 1.04 2.85 1.19 3.05.15.19 2.05 3.12 5.2 4.38.73.31 1.3.49 1.74.63.73.23 1.4.2 1.92.12.59-.09 1.71-.7 1.95-1.37.24-.67.24-1.25.17-1.37-.07-.11-.26-.18-.55-.32z\"\n fill={palette.fill}\n />\n <path\n d=\"M12 3.2C7.13 3.2 3.2 7.13 3.2 12c0 1.56.41 3.02 1.13 4.29L3.2 20.8l4.59-1.09A8.77 8.77 0 0 0 12 20.8c4.87 0 8.8-3.93 8.8-8.8s-3.93-8.8-8.8-8.8z\"\n stroke={palette.stroke}\n strokeWidth=\"1.2\"\n fill=\"none\"\n opacity=\"0.18\"\n />\n </>\n )}\n </XSocialIconShell>\n );\n}\n\nexport function XEmailIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.6}>\n {({ palette }) => (\n <>\n <rect x=\"4.5\" y=\"7\" width=\"15\" height=\"10\" rx=\"1.4\" stroke={palette.stroke} strokeWidth=\"1.6\" fill=\"none\" />\n <path d=\"M4.6 7.1l7.4 5.5 7.4-5.5\" stroke={palette.stroke} strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </>\n )}\n </XSocialIconShell>\n );\n}\n\nexport function XLinkedInIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.6}>\n {({ palette }) => (\n <>\n <path d=\"M8.1 9.1l2.6 2.6 4.1-4.1\" stroke={palette.stroke} strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n <path d=\"M6.8 10.2c1.6-1.6 4.3-1.6 5.9 0\" stroke={palette.stroke} strokeWidth=\"1.6\" strokeLinecap=\"round\" fill=\"none\" />\n <rect x=\"5\" y=\"5\" width=\"14\" height=\"14\" rx=\"3\" ry=\"3\" stroke={palette.stroke} strokeWidth=\"1.4\" fill=\"none\" opacity=\"0.12\" />\n </>\n )}\n </XSocialIconShell>\n );\n}\n\nexport function XTwitterIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.6}>\n {({ palette }) => (\n <>\n <path d=\"M7 4l7 8.7L7 21h2.2l7-8.7L21 4h-2.2l-7 8.7L7 4z\" fill={palette.fill} />\n <path d=\"M8 4h2.2l6.2 7.7\" stroke={palette.stroke} strokeWidth=\"1.2\" strokeLinecap=\"round\" fill=\"none\" opacity=\"0.2\" />\n </>\n )}\n </XSocialIconShell>\n );\n}\n\nexport function XGitHubIcon(props: XSocialIconProps) {\n return (\n <XSocialIconShell {...props} strokeWidth={props.strokeWidth ?? 1.35}>\n {({ palette }) => (\n <>\n <path\n d=\"M12 2c5.52 0 10 4.48 10 10 0 4.42-2.87 8.17-6.84 9.49.5.09.68-.22.68-.48 0-.24-.01-.87-.01-1.7 2.78.6 3.37-1.34 3.37-1.34.45-1.16 1.11-1.46 1.11-1.46.91-.62-.07-.61-.07-.61-1 .07-1.53 1.03-1.53 1.03-.89 1.53-2.34 1.54-2.91 1.19-.09-.92-.35-1.54-.63-1.9 2.22-.25 4.55-1.11 4.55-4.94 0-1.09-.39-1.98-1.03-2.68.1-.25.45-1.27-.1-2.65 0 0-.84-.27-2.75 1.03A9.58 9.58 0 0 0 12 6.84c-.85 0-1.7.12-2.51.34-1.91-1.3-2.75-1.03-2.75-1.03-.54 1.38-.2 2.4-.1 2.65-.63.7-1.03 1.59-1.03 2.68 0 3.84 2.33 4.69 4.54 4.94-.29.36-.55.97-.64 1.9-.57.35-2.02.34-2.91-1.19 0 0-.52-.96-1.53-1.03 0 0-.98-.01-.07.61 0 0 .66.3 1.11 1.46 0 0 .59 1.94 3.37 1.34 0 .83-.01 1.46-.01 1.7 0 .26.18.57.68.48C5.87 20.17 3 16.42 3 12 3 6.48 7.48 2 12 2z\"\n fill={palette.fill}\n />\n </>\n )}\n </XSocialIconShell>\n );\n}\n"],"mappings":";AAAA;;;AC+GQ,SAYE,KAZF;AA5EO,SAAR,eAAgC;AAAA,EACrC;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,eAAe;AAAA,EACf;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,UAAU;AAAA,IACd,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAEA,QAAM,eAAe;AAAA,IACnB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAEA,QAAM,eAAe;AAAA,IACnB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,QAAM,aAAa,QAAQ,SAAS,UAAU,SAAS,SAAS,WAAW,WAAW;AACtF,QAAM,iBACJ,YAAY,SAAS,UAAU,SAAS,SAAS,WAAW,WAAW;AACzE,QAAM,kBAAkB,aAAa,SAAS,UAAU,aAAa,SAAS,WAAW,SAAS;AAElG,QAAM,eAAe;AAAA,IACnB,aAAa,QAAQ,SAAS;AAAA,IAC9B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,eAAe;AAAA,IACf,eAAe,aAAa,SAAS;AAAA,IACrC,gBAAgB,aAAa,SAAS;AAAA,IACtC,cAAc,QAAQ,IAAI;AAAA,IAC1B,mBAAmB,UAAU,YAAY;AAAA,IACzC,GAAI,mBAAmB,EAAE,cAAc,gBAAgB;AAAA,IACvD,GAAI,oBAAoB,EAAE,gBAAgB,iBAAiB;AAAA,IAC3D,GAAI,yBAAyB,EAAE,sBAAsB,sBAAsB;AAAA,IAC3E,GAAI,eAAe,EAAE,kBAAkB,YAAY;AAAA,IACnD,GAAI,eAAe,EAAE,kBAAkB,YAAY;AAAA,IACnD,GAAI,aAAa,EAAE,gBAAgB,UAAU;AAAA,IAC7C,kBAAkB;AAAA,EACpB;AAEA,MAAI,iBAAiB,uBAAO;AAC5B,MAAI,MAAM;AACR,sBAAkB,IAAI,uBAAO,OAAO,IAAI,EAAE,CAAC;AAAA,EAC7C;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,cAAc,IAAI,uBAAO,IAAI,CAAC;AAAA,MAC5C,OAAO;AAAA,MAEN,gBAAM,IAAI,CAAC,SACV;AAAA,QAAC;AAAA;AAAA,UAEC,MAAM,KAAK;AAAA,UACX,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAW,uBAAO;AAAA,UAClB,OAAO,KAAK;AAAA,UACZ,OAAO;AAAA,YACL,GAAI,KAAK,aAAa,EAAE,qBAAqB,KAAK,UAAU;AAAA,YAC5D,GAAI,KAAK,kBAAkB,EAAE,2BAA2B,KAAK,eAAe;AAAA,UAC9E;AAAA,UAEA;AAAA,gCAAC,SAAI,WAAW,uBAAO,aAAc,eAAK,MAAK;AAAA,YAC9C,KAAK,QAAQ,oBAAC,UAAK,WAAW,uBAAO,MAAO,eAAK,MAAK;AAAA;AAAA;AAAA,QAZlD,KAAK;AAAA,MAaZ,CACD;AAAA;AAAA,EACH;AAEJ;;;AC/HA,SAAgB,gBAAgB;AA0EjB,SAyBP,UAzBO,OAAAA,MAYP,QAAAC,aAZO;AA7Cf,SAAS,iBAAiB;AAAA,EACxB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwD;AACtD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,SAAS,aAAa,aAAa,aAAa;AACtD,QAAM,OAAO,aAAa,iBAAiB,iBAAiB,aAAa;AACzE,QAAM,cAAc,cAAc;AAClC,QAAM,YAAY,wBAAwB;AAE1C,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,MAAM,QAAQ,QAAQ;AAAA,MACtB,cAAY;AAAA,MACZ,eAAa,QAAQ,SAAY;AAAA,MACjC,gBAAgB,MAAM,aAAa,IAAI;AAAA,MACvC,gBAAgB,MAAM,aAAa,KAAK;AAAA,MACxC,OAAO,EAAE,OAAO,QAAQ,GAAI,SAAS,CAAC,EAAG;AAAA,MACxC,GAAG;AAAA,MAEH;AAAA,gBAAQ,gBAAAD,KAAC,WAAO,iBAAM,IAAW;AAAA,QAClC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,MAAM,mBAAmB;AAAA,YACzB,QAAQ,kBAAkB,SAAS;AAAA,YACnC,eAAe,kBAAkB,SAAY;AAAA,YAC7C,aAAa,kBAAkB,SAAY;AAAA;AAAA,QAC7C;AAAA,QACC,SAAS,EAAE,QAAQ,CAAC;AAAA,QACpB,aACC,gBAAAC,MAAC,OACC;AAAA,0BAAAD,KAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM,MAAM,WAAW,QAAQ,aAAa,aAAY,KAAI;AAAA,UACtF,gBAAAA,KAAC,UAAK,GAAE,oDAAmD,QAAQ,aAAa,aAAY,QAAO,eAAc,SAAQ;AAAA,WAC3H;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEO,SAAS,cAAc,OAAyB;AACrD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,KAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAC,MAAA,YACE;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,QAAQ,QAAQ;AAAA,QAChB,aAAY;AAAA,QACZ,eAAc;AAAA,QACd,gBAAe;AAAA,QACf,MAAK;AAAA;AAAA,IACP;AAAA,IACA,gBAAAA,KAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,QAAO,MAAK,QAAO,QAAQ,QAAQ,QAAQ,eAAc,QAAO,aAAY,KAAI;AAAA,KAC5G,GAEJ;AAEJ;AAEO,SAAS,eAAe,OAAyB;AACtD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,KAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAC,MAAA,YACE;AAAA,oBAAAD,KAAC,UAAK,GAAE,OAAM,GAAE,OAAM,OAAM,QAAO,QAAO,QAAO,IAAG,OAAM,IAAG,OAAM,QAAQ,QAAQ,QAAQ,aAAY,OAAM,MAAK,QAAO;AAAA,IACzH,gBAAAA,KAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,QAAO,QAAQ,QAAQ,QAAQ,aAAY,OAAM,MAAK,QAAO;AAAA,IACvF,gBAAAA,KAAC,YAAO,IAAG,QAAO,IAAG,OAAM,GAAE,OAAM,MAAM,QAAQ,MAAM;AAAA,KACzD,GAEJ;AAEJ;AAEO,SAAS,cAAc,OAAyB;AACrD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,KAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAC,MAAA,YACE;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAM,QAAQ;AAAA;AAAA,IAChB;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,QAAQ,QAAQ;AAAA,QAChB,aAAY;AAAA,QACZ,MAAK;AAAA,QACL,SAAQ;AAAA;AAAA,IACV;AAAA,KACF,GAEJ;AAEJ;AAEO,SAAS,WAAW,OAAyB;AAClD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,KAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAC,MAAA,YACE;AAAA,oBAAAD,KAAC,UAAK,GAAE,OAAM,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,OAAM,QAAQ,QAAQ,QAAQ,aAAY,OAAM,MAAK,QAAO;AAAA,IAC1G,gBAAAA,KAAC,UAAK,GAAE,4BAA2B,QAAQ,QAAQ,QAAQ,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,MAAK,QAAO;AAAA,KACxI,GAEJ;AAEJ;AAEO,SAAS,cAAc,OAAyB;AACrD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,KAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAC,MAAA,YACE;AAAA,oBAAAD,KAAC,UAAK,GAAE,4BAA2B,QAAQ,QAAQ,QAAQ,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,MAAK,QAAO;AAAA,IACtI,gBAAAA,KAAC,UAAK,GAAE,mCAAkC,QAAQ,QAAQ,QAAQ,aAAY,OAAM,eAAc,SAAQ,MAAK,QAAO;AAAA,IACtH,gBAAAA,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,IAAG,KAAI,QAAQ,QAAQ,QAAQ,aAAY,OAAM,MAAK,QAAO,SAAQ,QAAO;AAAA,KAC9H,GAEJ;AAEJ;AAEO,SAAS,aAAa,OAAyB;AACpD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,KAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAC,MAAA,YACE;AAAA,oBAAAD,KAAC,UAAK,GAAE,mDAAkD,MAAM,QAAQ,MAAM;AAAA,IAC9E,gBAAAA,KAAC,UAAK,GAAE,oBAAmB,QAAQ,QAAQ,QAAQ,aAAY,OAAM,eAAc,SAAQ,MAAK,QAAO,SAAQ,OAAM;AAAA,KACvH,GAEJ;AAEJ;AAEO,SAAS,YAAY,OAAyB;AACnD,SACE,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,aAAa,MAAM,eAAe,MAC5D,WAAC,EAAE,QAAQ,MACV,gBAAAA,KAAA,YACE,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC,GAAE;AAAA,MACF,MAAM,QAAQ;AAAA;AAAA,EAChB,GACF,GAEJ;AAEJ;","names":["jsx","jsxs"]}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
|
|
3
|
-
interface WordConfig {
|
|
4
|
-
text: string;
|
|
5
|
-
type: "normal" | "underline" | "button" | "blur1" | "blur2";
|
|
6
|
-
breakAfter?: boolean;
|
|
7
|
-
italic?: boolean;
|
|
8
|
-
bold?: boolean;
|
|
9
|
-
}
|
|
10
|
-
interface XInteractivePhraseProps {
|
|
11
|
-
words: WordConfig[];
|
|
12
|
-
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span";
|
|
13
|
-
className?: string;
|
|
14
|
-
}
|
|
15
|
-
declare function XInteractivePhrase({ words, as: Tag, className }: XInteractivePhraseProps): react_jsx_runtime.JSX.Element;
|
|
16
|
-
|
|
17
|
-
export { type WordConfig, XInteractivePhrase, type XInteractivePhraseProps };
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
|
|
3
|
-
interface XContactFormProps {
|
|
4
|
-
showName?: boolean;
|
|
5
|
-
showEmail?: boolean;
|
|
6
|
-
showPhone?: boolean;
|
|
7
|
-
showSubject?: boolean;
|
|
8
|
-
showMessage?: boolean;
|
|
9
|
-
namePlaceholder?: string;
|
|
10
|
-
emailPlaceholder?: string;
|
|
11
|
-
phonePlaceholder?: string;
|
|
12
|
-
subjectPlaceholder?: string;
|
|
13
|
-
messagePlaceholder?: string;
|
|
14
|
-
labelColor?: string;
|
|
15
|
-
wrapperBackgroundColor?: string;
|
|
16
|
-
wrapperBorderColor?: string;
|
|
17
|
-
wrapperBorderWidth?: string;
|
|
18
|
-
wrapperBorderRadius?: "rounded" | "square";
|
|
19
|
-
wrapperBorderStyle?: "solid" | "dashed" | "dotted";
|
|
20
|
-
fieldBorderColor?: string;
|
|
21
|
-
fieldBorderWidth?: string;
|
|
22
|
-
fieldBorderRadius?: "rounded" | "square";
|
|
23
|
-
fieldBorderStyle?: "solid" | "dashed" | "dotted";
|
|
24
|
-
buttonColor?: string;
|
|
25
|
-
buttonBorderColor?: string;
|
|
26
|
-
buttonBorderWidth?: string;
|
|
27
|
-
buttonBorderRadius?: "rounded" | "square";
|
|
28
|
-
buttonBorderStyle?: "solid" | "dashed" | "dotted";
|
|
29
|
-
buttonHoverColor?: string;
|
|
30
|
-
buttonHoverTextColor?: string;
|
|
31
|
-
buttonHoverBorderColor?: string;
|
|
32
|
-
buttonTextColor?: string;
|
|
33
|
-
buttonAlignment?: "left" | "right";
|
|
34
|
-
requiredFieldsMessage?: string;
|
|
35
|
-
honeypotMessage?: string;
|
|
36
|
-
submitSuccessMessage?: string;
|
|
37
|
-
statusSuccessColor?: string;
|
|
38
|
-
statusErrorColor?: string;
|
|
39
|
-
decorativeX?: boolean;
|
|
40
|
-
decorativeXColor?: string;
|
|
41
|
-
size?: "small" | "medium" | "large";
|
|
42
|
-
layout?: "vertical" | "grid";
|
|
43
|
-
}
|
|
44
|
-
declare function XContactForm({ showName, showEmail, showPhone, showSubject, showMessage, namePlaceholder, emailPlaceholder, phonePlaceholder, subjectPlaceholder, messagePlaceholder, labelColor, wrapperBackgroundColor, wrapperBorderColor, wrapperBorderWidth, wrapperBorderRadius, wrapperBorderStyle, fieldBorderColor, fieldBorderWidth, fieldBorderRadius, fieldBorderStyle, buttonColor, buttonBorderColor, buttonBorderWidth, buttonBorderRadius, buttonBorderStyle, buttonHoverColor, buttonHoverTextColor, buttonHoverBorderColor, buttonTextColor, buttonAlignment, requiredFieldsMessage, honeypotMessage, submitSuccessMessage, statusSuccessColor, statusErrorColor, decorativeX, decorativeXColor, size, layout, }: XContactFormProps): react_jsx_runtime.JSX.Element;
|
|
45
|
-
|
|
46
|
-
interface XNewsletterProps {
|
|
47
|
-
title?: string;
|
|
48
|
-
placeholder?: string;
|
|
49
|
-
buttonText?: string;
|
|
50
|
-
termsText?: string;
|
|
51
|
-
termsLinkText?: string;
|
|
52
|
-
successMessage?: string;
|
|
53
|
-
errorMessage?: string;
|
|
54
|
-
termsErrorMessage?: string;
|
|
55
|
-
termsLink?: string;
|
|
56
|
-
apiRoute: string;
|
|
57
|
-
method?: "POST" | "GET" | "PUT";
|
|
58
|
-
payloadType?: "formData" | "json";
|
|
59
|
-
layout?: "horizontal" | "vertical";
|
|
60
|
-
accentColor?: string;
|
|
61
|
-
textColor?: string;
|
|
62
|
-
borderColor?: string;
|
|
63
|
-
buttonTextColor?: string;
|
|
64
|
-
containerClassName?: string;
|
|
65
|
-
}
|
|
66
|
-
declare function XNewsletter({ title, placeholder, buttonText, termsText, termsLinkText, successMessage, errorMessage, termsErrorMessage, termsLink, apiRoute, method, payloadType, layout, accentColor, textColor, borderColor, buttonTextColor, containerClassName, }: XNewsletterProps): react_jsx_runtime.JSX.Element;
|
|
67
|
-
|
|
68
|
-
export { XContactForm, type XContactFormProps, XNewsletter, type XNewsletterProps };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
-
|
|
4
|
-
interface XMicroGalleryImage {
|
|
5
|
-
src: string;
|
|
6
|
-
alt: string;
|
|
7
|
-
}
|
|
8
|
-
interface XMicroGalleryTextProps {
|
|
9
|
-
images: XMicroGalleryImage[];
|
|
10
|
-
text: React.ReactNode;
|
|
11
|
-
textPosition?: 'left' | 'right';
|
|
12
|
-
textAlign?: 'left' | 'right' | 'center';
|
|
13
|
-
autoShuffle?: boolean;
|
|
14
|
-
shuffleInterval?: number;
|
|
15
|
-
}
|
|
16
|
-
declare const XMicroGalleryText: React.FC<XMicroGalleryTextProps>;
|
|
17
|
-
|
|
18
|
-
interface XStaticGalleryImage {
|
|
19
|
-
src: string;
|
|
20
|
-
alt: string;
|
|
21
|
-
}
|
|
22
|
-
interface XStaticGalleryProps {
|
|
23
|
-
images: XStaticGalleryImage[];
|
|
24
|
-
columns?: 1 | 2 | 3 | 4 | 5;
|
|
25
|
-
title?: string;
|
|
26
|
-
}
|
|
27
|
-
declare function XStaticGallery({ images, columns, title }: XStaticGalleryProps): react_jsx_runtime.JSX.Element;
|
|
28
|
-
|
|
29
|
-
export { type XMicroGalleryImage, XMicroGalleryText, type XMicroGalleryTextProps, XStaticGallery, type XStaticGalleryImage, type XStaticGalleryProps };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { XContactForm, XContactFormProps, XNewsletter, XNewsletterProps } from './forms/index.mjs';
|
|
2
|
-
export { IconRenderer, NavLinkItem, ThemeToggleIcons, XNavbar, XNavbarProps } from './navigation/index.mjs';
|
|
3
|
-
export { CopyrightConfig, XFooter, XFooterLink, XFooterProps, XSeparator, XSeparatorProps, XZigZagLayout, XZigZagLayoutProps } from './layout/index.mjs';
|
|
4
|
-
export { WordConfig, XInteractivePhrase, XInteractivePhraseProps } from './content/index.mjs';
|
|
5
|
-
export { XMicroGalleryImage, XMicroGalleryText, XMicroGalleryTextProps, XStaticGallery, XStaticGalleryImage, XStaticGalleryProps } from './gallery/index.mjs';
|
|
6
|
-
export { SocialItem, XEmailIcon, XGitHubIcon, XInstagramIcon, XLinkedInIcon, XSocialContact, XSocialContactProps, XSocialIconProps, XTelegramIcon, XTwitterIcon, XWhatsappIcon } from './social/index.mjs';
|
|
7
|
-
import 'react/jsx-runtime';
|
|
8
|
-
import 'react';
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import React, { HTMLAttributes } from 'react';
|
|
3
|
-
|
|
4
|
-
type XFooterLink = {
|
|
5
|
-
label: string;
|
|
6
|
-
href: string;
|
|
7
|
-
};
|
|
8
|
-
type CopyrightConfig = {
|
|
9
|
-
text?: string;
|
|
10
|
-
showYear?: boolean;
|
|
11
|
-
customYear?: number | string;
|
|
12
|
-
yearFirst?: boolean;
|
|
13
|
-
};
|
|
14
|
-
type XFooterProps = {
|
|
15
|
-
links: XFooterLink[];
|
|
16
|
-
copyright?: CopyrightConfig;
|
|
17
|
-
layout?: "horizontal" | "vertical";
|
|
18
|
-
columns?: 1 | 2 | 3 | 4;
|
|
19
|
-
colors?: {
|
|
20
|
-
bg?: string;
|
|
21
|
-
text?: string;
|
|
22
|
-
accent?: string;
|
|
23
|
-
border?: string;
|
|
24
|
-
};
|
|
25
|
-
className?: string;
|
|
26
|
-
};
|
|
27
|
-
declare function XFooter({ links, copyright, layout, columns, colors, className, }: XFooterProps): react_jsx_runtime.JSX.Element;
|
|
28
|
-
|
|
29
|
-
interface XSeparatorProps {
|
|
30
|
-
orientation?: 'horizontal' | 'vertical';
|
|
31
|
-
variant?: 'solid' | 'dashed' | 'dotted';
|
|
32
|
-
isFaded?: boolean;
|
|
33
|
-
hasX?: boolean;
|
|
34
|
-
xColor?: string;
|
|
35
|
-
xBg?: string;
|
|
36
|
-
thickness?: string;
|
|
37
|
-
color?: string;
|
|
38
|
-
gap?: string;
|
|
39
|
-
className?: string;
|
|
40
|
-
}
|
|
41
|
-
declare function XSeparator({ orientation, variant, isFaded, hasX, xColor, xBg, thickness, color, gap, className }: XSeparatorProps): react_jsx_runtime.JSX.Element;
|
|
42
|
-
|
|
43
|
-
type XZigZagLayoutProps = HTMLAttributes<HTMLDivElement> & {
|
|
44
|
-
children: React.ReactNode;
|
|
45
|
-
startSide?: "left" | "right";
|
|
46
|
-
gap?: number | string;
|
|
47
|
-
offset?: number | string;
|
|
48
|
-
textAlign?: "inherit" | "side" | "left" | "right";
|
|
49
|
-
showLine?: boolean;
|
|
50
|
-
lineColor?: string;
|
|
51
|
-
lineThickness?: number | string;
|
|
52
|
-
};
|
|
53
|
-
declare function XZigZagLayout({ children, className, style, startSide, gap, offset, textAlign, showLine, lineColor, lineThickness, ...rest }: XZigZagLayoutProps): react_jsx_runtime.JSX.Element;
|
|
54
|
-
|
|
55
|
-
export { type CopyrightConfig, XFooter, type XFooterLink, type XFooterProps, XSeparator, type XSeparatorProps, XZigZagLayout, type XZigZagLayoutProps };
|