luna-components-library 1.1.25 → 1.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -13
- package/dist/luna-components-library.js +112 -3
- package/dist/luna-components-library.js.map +1 -1
- package/dist/src/components/Modal.d.ts +44 -0
- package/dist/src/components/WhatsApp.d.ts +3 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/examples/ModalDataExample.d.ts +2 -0
- package/package.json +54 -54
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ To ensure Tailwind CSS successfully generates and includes the necessary utility
|
|
|
47
47
|
## 🚀 Quick Start
|
|
48
48
|
|
|
49
49
|
```jsx
|
|
50
|
-
import { Button, Card, Anchor, Accordion, Spinner, DropDown, ProgressBar, Preloader, ScrollTop } from 'luna-components-library';
|
|
50
|
+
import { Button, Card, Anchor, Accordion, Spinner, DropDown, ProgressBar, Preloader, ScrollTop, Modal } from 'luna-components-library';
|
|
51
51
|
|
|
52
52
|
function App() {
|
|
53
53
|
return (
|
|
@@ -97,18 +97,13 @@ function App() {
|
|
|
97
97
|
onChange={(value) => console.log('Selected:', value)}
|
|
98
98
|
/>
|
|
99
99
|
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<Preloader
|
|
108
|
-
isLoading={isLoading}
|
|
109
|
-
duration={2000}
|
|
110
|
-
onComplete={() => setIsLoading(false)}
|
|
111
|
-
/>
|
|
100
|
+
<Modal
|
|
101
|
+
show={true}
|
|
102
|
+
onHide={() => console.log('Modal closed')}
|
|
103
|
+
title="Modal Title"
|
|
104
|
+
>
|
|
105
|
+
<p>This is a modal component from Luna Components Library.</p>
|
|
106
|
+
</Modal>
|
|
112
107
|
|
|
113
108
|
<ScrollTop
|
|
114
109
|
threshold={200}
|
|
@@ -537,6 +532,155 @@ type WhatsAppPosition = 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-
|
|
|
537
532
|
type WhatsAppSize = 'sm' | 'md' | 'lg';
|
|
538
533
|
```
|
|
539
534
|
|
|
535
|
+
### Modal
|
|
536
|
+
A flexible modal component for displaying dialogs, forms, and overlays.
|
|
537
|
+
|
|
538
|
+
```jsx
|
|
539
|
+
<Modal
|
|
540
|
+
show={showModal}
|
|
541
|
+
onHide={() => setShowModal(false)}
|
|
542
|
+
title="Modal Title"
|
|
543
|
+
size="lg"
|
|
544
|
+
centered
|
|
545
|
+
>
|
|
546
|
+
<p>Modal content goes here.</p>
|
|
547
|
+
<Modal.Footer>
|
|
548
|
+
<Button variant="secondary" onClick={() => setShowModal(false)}>
|
|
549
|
+
Close
|
|
550
|
+
</Button>
|
|
551
|
+
<Button onClick={handleSave}>Save Changes</Button>
|
|
552
|
+
</Modal.Footer>
|
|
553
|
+
</Modal>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Props:**
|
|
557
|
+
- `show: boolean` - Whether the modal is visible
|
|
558
|
+
- `onHide: () => void` - Callback when modal is closed
|
|
559
|
+
- `size?: ModalSize` - Modal size (default: 'md')
|
|
560
|
+
- `centered?: boolean` - Whether to center the modal vertically (default: false)
|
|
561
|
+
- `backdrop?: boolean | 'static'` - Backdrop overlay behavior (default: true)
|
|
562
|
+
- `backdropClose?: boolean` - Whether clicking backdrop closes modal (default: true)
|
|
563
|
+
- `keyboard?: boolean` - Whether ESC key closes modal (default: true)
|
|
564
|
+
- `animation?: boolean` - Whether to show animations (default: true)
|
|
565
|
+
- `title?: React.ReactNode` - Modal title
|
|
566
|
+
- `header?: React.ReactNode` - Custom header content
|
|
567
|
+
- `children: React.ReactNode` - Modal body content
|
|
568
|
+
- `footer?: React.ReactNode` - Custom footer content
|
|
569
|
+
- `closeButton?: boolean` - Whether to show close button (default: true)
|
|
570
|
+
- `className?: string` - Additional CSS classes for the modal
|
|
571
|
+
- `dialogClassName?: string` - CSS classes for the modal dialog
|
|
572
|
+
- `contentClassName?: string` - CSS classes for the modal content
|
|
573
|
+
- `headerClassName?: string` - CSS classes for the modal header
|
|
574
|
+
- `bodyClassName?: string` - CSS classes for the modal body
|
|
575
|
+
- `footerClassName?: string` - CSS classes for the modal footer
|
|
576
|
+
|
|
577
|
+
**Types:**
|
|
578
|
+
```typescript
|
|
579
|
+
type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
**Examples:**
|
|
583
|
+
```jsx
|
|
584
|
+
// Basic modal
|
|
585
|
+
<Modal show={show} onHide={handleClose}>
|
|
586
|
+
<p>Simple modal content</p>
|
|
587
|
+
</Modal>
|
|
588
|
+
|
|
589
|
+
// Large centered modal with custom footer
|
|
590
|
+
<Modal
|
|
591
|
+
show={show}
|
|
592
|
+
onHide={handleClose}
|
|
593
|
+
size="lg"
|
|
594
|
+
centered
|
|
595
|
+
title="Confirm Action"
|
|
596
|
+
>
|
|
597
|
+
<p>Are you sure you want to proceed?</p>
|
|
598
|
+
<div className="mt-4">
|
|
599
|
+
<Button variant="secondary" onClick={handleClose}>Cancel</Button>
|
|
600
|
+
<Button onClick={handleConfirm}>Confirm</Button>
|
|
601
|
+
</div>
|
|
602
|
+
</Modal>
|
|
603
|
+
|
|
604
|
+
// Static backdrop (can't close by clicking outside)
|
|
605
|
+
<Modal
|
|
606
|
+
show={show}
|
|
607
|
+
onHide={handleClose}
|
|
608
|
+
backdrop="static"
|
|
609
|
+
backdropClose={false}
|
|
610
|
+
>
|
|
611
|
+
<p>This modal requires explicit action to close.</p>
|
|
612
|
+
</Modal>
|
|
613
|
+
|
|
614
|
+
// Custom styled modal
|
|
615
|
+
<Modal
|
|
616
|
+
show={show}
|
|
617
|
+
onHide={handleClose}
|
|
618
|
+
contentClassName="bg-dark text-white"
|
|
619
|
+
headerClassName="bg-secondary"
|
|
620
|
+
>
|
|
621
|
+
<p>Dark themed modal</p>
|
|
622
|
+
</Modal>
|
|
623
|
+
|
|
624
|
+
// Modal with data flow (parent to child and child to parent)
|
|
625
|
+
interface FormData {
|
|
626
|
+
name: string;
|
|
627
|
+
email: string;
|
|
628
|
+
message: string;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
const MyComponent = () => {
|
|
632
|
+
const [showModal, setShowModal] = useState(false);
|
|
633
|
+
const [formData, setFormData] = useState<FormData>({
|
|
634
|
+
name: '',
|
|
635
|
+
email: '',
|
|
636
|
+
message: ''
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// Pass data to modal
|
|
640
|
+
const openEditModal = (data: FormData) => {
|
|
641
|
+
setFormData(data);
|
|
642
|
+
setShowModal(true);
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
// Receive data from modal
|
|
646
|
+
const handleSubmit = (data: FormData) => {
|
|
647
|
+
console.log('Data from modal:', data);
|
|
648
|
+
// Process data (API call, etc.)
|
|
649
|
+
setShowModal(false);
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
return (
|
|
653
|
+
<Modal show={showModal} onHide={() => setShowModal(false)} title="Edit Data">
|
|
654
|
+
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(formData); }}>
|
|
655
|
+
<input
|
|
656
|
+
value={formData.name}
|
|
657
|
+
onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
|
|
658
|
+
placeholder="Name"
|
|
659
|
+
className="w-full p-2 border rounded mb-2"
|
|
660
|
+
/>
|
|
661
|
+
<input
|
|
662
|
+
value={formData.email}
|
|
663
|
+
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
|
|
664
|
+
placeholder="Email"
|
|
665
|
+
className="w-full p-2 border rounded mb-2"
|
|
666
|
+
/>
|
|
667
|
+
<textarea
|
|
668
|
+
value={formData.message}
|
|
669
|
+
onChange={(e) => setFormData(prev => ({ ...prev, message: e.target.value }))}
|
|
670
|
+
placeholder="Message"
|
|
671
|
+
className="w-full p-2 border rounded mb-2"
|
|
672
|
+
rows={3}
|
|
673
|
+
/>
|
|
674
|
+
<div className="flex gap-2">
|
|
675
|
+
<Button variant="secondary" onClick={() => setShowModal(false)}>Cancel</Button>
|
|
676
|
+
<Button onClick={() => handleSubmit(formData)}>Save</Button>
|
|
677
|
+
</div>
|
|
678
|
+
</form>
|
|
679
|
+
</Modal>
|
|
680
|
+
);
|
|
681
|
+
};
|
|
682
|
+
```
|
|
683
|
+
|
|
540
684
|
## 🛠️ Development
|
|
541
685
|
|
|
542
686
|
### Prerequisites
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
4
|
//#endregion
|
|
@@ -547,7 +547,7 @@ var ScrollTop = ({ threshold = 100, className = "", children, position = "bottom
|
|
|
547
547
|
};
|
|
548
548
|
//#endregion
|
|
549
549
|
//#region src/components/WhatsApp.tsx
|
|
550
|
-
var WhatsApp = ({ phone = "", message = "¡Hola! Me gustaría obtener más información.", position = "bottom-right", size = "md", showTooltip = true, tooltipText = "¿En qué podemos ayudarte?", className = "", style, onClick, zIndex = 50, openInNewTab = true }) => {
|
|
550
|
+
var WhatsApp = ({ phone = "", message = "¡Hola! Me gustaría obtener más información.", position = "bottom-right", size = "md", showTooltip = true, tooltipText = "¿En qué podemos ayudarte?", className = "", tooltipClassName = "", style, onClick, zIndex = 50, openInNewTab = true }) => {
|
|
551
551
|
const [isHovered, setIsHovered] = useState(false);
|
|
552
552
|
if (!phone) return null;
|
|
553
553
|
const handleWhatsAppClick = () => {
|
|
@@ -611,12 +611,121 @@ var WhatsApp = ({ phone = "", message = "¡Hola! Me gustaría obtener más infor
|
|
|
611
611
|
transition-opacity duration-300
|
|
612
612
|
${isHovered ? "opacity-100" : "opacity-0"}
|
|
613
613
|
${position.includes("right") ? "right-20" : position.includes("left") ? "left-20" : "left-1/2 transform -translate-x-1/2"}
|
|
614
|
+
${tooltipClassName}
|
|
614
615
|
`,
|
|
615
616
|
style: { [position.includes("bottom") ? "bottom" : "top"]: position.includes("bottom") ? "5.5rem" : "5.5rem" },
|
|
616
617
|
children: tooltipText
|
|
617
618
|
})] });
|
|
618
619
|
};
|
|
619
620
|
//#endregion
|
|
620
|
-
|
|
621
|
+
//#region src/components/Modal.tsx
|
|
622
|
+
var Modal = ({ show, onHide, size = "md", centered = false, backdrop = true, backdropClose = true, keyboard = true, animation = true, className = "", dialogClassName = "", contentClassName = "", headerClassName = "", bodyClassName = "", footerClassName = "", title, header, children, footer, closeButton = true }) => {
|
|
623
|
+
const modalRef = useRef(null);
|
|
624
|
+
const previousActiveElement = useRef(null);
|
|
625
|
+
useEffect(() => {
|
|
626
|
+
if (!show || !keyboard) return;
|
|
627
|
+
const handleEscape = (event) => {
|
|
628
|
+
if (event.key === "Escape") onHide();
|
|
629
|
+
};
|
|
630
|
+
document.addEventListener("keydown", handleEscape);
|
|
631
|
+
return () => document.removeEventListener("keydown", handleEscape);
|
|
632
|
+
}, [
|
|
633
|
+
show,
|
|
634
|
+
keyboard,
|
|
635
|
+
onHide
|
|
636
|
+
]);
|
|
637
|
+
const handleBackdropClick = (event) => {
|
|
638
|
+
if (backdropClose) {
|
|
639
|
+
const target = event.target;
|
|
640
|
+
if (target.getAttribute("data-backdrop") === "true" || target.closest("[data-backdrop=\"true\"]")) onHide();
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
useEffect(() => {
|
|
644
|
+
if (show) {
|
|
645
|
+
previousActiveElement.current = document.activeElement;
|
|
646
|
+
if (modalRef.current) modalRef.current.focus();
|
|
647
|
+
document.body.style.overflow = "hidden";
|
|
648
|
+
} else {
|
|
649
|
+
if (previousActiveElement.current) previousActiveElement.current.focus();
|
|
650
|
+
document.body.style.overflow = "";
|
|
651
|
+
}
|
|
652
|
+
return () => {
|
|
653
|
+
document.body.style.overflow = "";
|
|
654
|
+
};
|
|
655
|
+
}, [show]);
|
|
656
|
+
const sizeClasses = {
|
|
657
|
+
sm: "max-w-sm",
|
|
658
|
+
md: "max-w-md",
|
|
659
|
+
lg: "max-w-lg",
|
|
660
|
+
xl: "max-w-xl"
|
|
661
|
+
};
|
|
662
|
+
const modalClasses = `
|
|
663
|
+
fixed inset-0 z-60 flex items-center justify-center
|
|
664
|
+
${show ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}
|
|
665
|
+
${animation ? "transition-opacity duration-300" : ""}
|
|
666
|
+
${className}
|
|
667
|
+
`.trim();
|
|
668
|
+
const dialogClasses = `
|
|
669
|
+
relative w-full ${sizeClasses[size]} mx-auto
|
|
670
|
+
${centered ? "flex items-center justify-center min-h-screen" : "mt-8"}
|
|
671
|
+
${dialogClassName}
|
|
672
|
+
`.trim();
|
|
673
|
+
if (!show) return null;
|
|
674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
675
|
+
ref: modalRef,
|
|
676
|
+
className: modalClasses,
|
|
677
|
+
tabIndex: -1,
|
|
678
|
+
role: "dialog",
|
|
679
|
+
"aria-modal": "true",
|
|
680
|
+
"aria-labelledby": title ? "modal-title" : void 0,
|
|
681
|
+
children: [backdrop && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
682
|
+
"data-backdrop": "true",
|
|
683
|
+
className: `absolute inset-0 bg-black bg-opacity-50 ${animation ? "transition-opacity duration-300" : ""} ${show ? "opacity-100" : "opacity-0"}`,
|
|
684
|
+
onClick: handleBackdropClick
|
|
685
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
686
|
+
className: dialogClasses,
|
|
687
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
688
|
+
className: `bg-white rounded-lg shadow-xl relative z-10 ${contentClassName}`,
|
|
689
|
+
children: [
|
|
690
|
+
(header || title || closeButton) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
691
|
+
className: `flex items-center justify-between p-4 border-b border-gray-200 ${headerClassName}`,
|
|
692
|
+
children: [header || title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
|
|
693
|
+
className: "text-lg font-semibold text-gray-900",
|
|
694
|
+
id: "modal-title",
|
|
695
|
+
children: title
|
|
696
|
+
}), closeButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
697
|
+
type: "button",
|
|
698
|
+
className: "text-gray-400 hover:text-gray-600 transition-colors",
|
|
699
|
+
onClick: onHide,
|
|
700
|
+
"aria-label": "Close",
|
|
701
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
|
|
702
|
+
className: "w-6 h-6",
|
|
703
|
+
fill: "none",
|
|
704
|
+
stroke: "currentColor",
|
|
705
|
+
viewBox: "0 0 24 24",
|
|
706
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
|
|
707
|
+
strokeLinecap: "round",
|
|
708
|
+
strokeLinejoin: "round",
|
|
709
|
+
strokeWidth: 2,
|
|
710
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
711
|
+
})
|
|
712
|
+
})
|
|
713
|
+
})]
|
|
714
|
+
}),
|
|
715
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
716
|
+
className: `p-4 ${bodyClassName}`,
|
|
717
|
+
children
|
|
718
|
+
}),
|
|
719
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
720
|
+
className: `flex items-center justify-end p-4 border-t border-gray-200 space-x-2 ${footerClassName}`,
|
|
721
|
+
children: footer
|
|
722
|
+
})
|
|
723
|
+
]
|
|
724
|
+
})
|
|
725
|
+
})]
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
//#endregion
|
|
729
|
+
export { Accordion, Anchor, Button, Card, DropDown, Modal, Preloader, ProgressBar, ScrollTop, Spinner, Typed, WhatsApp };
|
|
621
730
|
|
|
622
731
|
//# sourceMappingURL=luna-components-library.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"luna-components-library.js","names":[],"sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/jsx-runtime.js","../src/components/Button.tsx","../src/components/Card.tsx","../src/components/Anchor.tsx","../src/components/Accordion.tsx","../src/components/Spinner.tsx","../src/components/DropDown.tsx","../src/components/ProgressBar.tsx","../src/components/Typed.tsx","../src/components/Preloader.tsx","../src/components/ScrollTop.tsx","../src/components/WhatsApp.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import React from 'react';\n\n// Button variants and sizes\ntype ButtonVariant = 'primary' | 'secondary' | 'outline';\ntype ButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps {\n children: React.ReactNode;\n variant?: ButtonVariant;\n size?: ButtonSize;\n onClick?: () => void;\n disabled?: boolean;\n className?: string;\n containerClassName?: string;\n variantClassName?: string;\n sizeClassName?: string;\n}\n\n{/* onCLick default should open window.open('https://andreychaconresumereact.netlify.app/', '_blank') */ }\n\nconst Button = ({\n children,\n variant = 'primary',\n size = 'sm',\n onClick = () =>\n void 0,\n disabled = false,\n className = '',\n containerClassName = 'font-medium rounded-lg transition-colors focus:outline-none focus:ring-2',\n variantClassName = 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',\n sizeClassName = 'px-3 py-1.5 text-sm'\n}: ButtonProps) => {\n const baseClasses = containerClassName;\n\n const variantClasses = {\n primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',\n secondary: 'bg-gray-600 text-white hover:bg-gray-700 focus:ring-gray-500',\n outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50 focus:ring-gray-500',\n };\n\n const sizeClasses = {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n };\n\n const classes = `\n ${baseClasses}\n ${variantClasses[variant]}\n ${sizeClasses[size]}\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${className}\n `.trim();\n\n return (\n <button\n className={classes}\n onClick={onClick}\n disabled={disabled}\n >\n {children}\n </button>\n );\n};\n\nexport default Button;\n","import React from 'react';\n\n// Card padding and shadow variants\ntype CardPadding = 'none' | 'sm' | 'md' | 'lg';\ntype CardShadow = 'none' | 'sm' | 'md' | 'lg';\n\nexport interface CardProps {\n children: React.ReactNode;\n title?: string;\n className?: string;\n containerClassName?: string;\n titleClassName?: string;\n padding?: CardPadding;\n shadow?: CardShadow;\n}\n\nconst Card = ({\n children,\n title,\n className = '',\n containerClassName = 'bg-white rounded-lg border border-gray-200',\n titleClassName = 'text-lg font-semibold text-gray-900',\n padding = 'md',\n shadow = 'md',\n}: CardProps) => {\n const paddingClasses = {\n none: '',\n sm: 'p-3',\n md: 'p-4',\n lg: 'p-6',\n };\n\n const shadowClasses = {\n none: '',\n sm: 'shadow-sm',\n md: 'shadow-md',\n lg: 'shadow-lg',\n };\n\n const classes = `\n ${containerClassName}\n ${paddingClasses[padding]}\n ${shadowClasses[shadow]}\n ${className}\n `.trim();\n\n return (\n <div className={classes}>\n {title && (\n <div className=\"mb-4\">\n <h3 className={titleClassName}>{title}</h3>\n </div>\n )}\n {children}\n </div>\n );\n};\n\nexport default Card;\n","import React from 'react';\r\n\r\n// Anchor link variants and sizes\r\ntype AnchorVariant = 'none' | 'primary' | 'secondary' | 'outline';\r\ntype AnchorSize = 'sm' | 'md' | 'lg';\r\n\r\nexport interface AnchorProps {\r\n children?: React.ReactNode;\r\n variant?: AnchorVariant;\r\n size?: AnchorSize;\r\n href?: string;\r\n className?: string;\r\n containerClassName?: string;\r\n variantClassName?: string;\r\n sizeClassName?: string;\r\n target?: string;\r\n rel?: string;\r\n}\r\n\r\nconst Anchor = ({\r\n children = \"Pablo Andrey Chacon Luna\",\r\n variant = 'none',\r\n size = 'sm',\r\n href = 'https://andreychaconresumereact.netlify.app/',\r\n className,\r\n containerClassName = 'font-medium rounded-lg transition-colors focus:outline-none focus:ring-2',\r\n variantClassName = 'bg-blue-600 text-white hover:bg-blue-700',\r\n sizeClassName = 'px-3 py-1.5 text-sm',\r\n target = '_blank',\r\n rel = 'noopener noreferrer'\r\n}: AnchorProps) => {\r\n\r\n const baseClasses = containerClassName;\r\n\r\n const variantClasses = {\r\n none: '',\r\n primary: 'bg-blue-600 text-white hover:bg-blue-700',\r\n secondary: 'bg-gray-600 text-white hover:bg-gray-700',\r\n outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50',\r\n };\r\n\r\n const sizeClasses = {\r\n sm: 'px-3 py-1.5 text-sm',\r\n md: 'px-4 py-2 text-base',\r\n lg: 'px-6 py-3 text-lg',\r\n };\r\n\r\n const classes = `\r\n ${baseClasses}\r\n ${variantClasses[variant]}\r\n ${sizeClasses[size]}\r\n ${variantClassName}\r\n ${sizeClassName}\r\n ${className}\r\n `.trim();\r\n\r\n return (\r\n <a href={href} target={target} rel={rel} className={classes}>\r\n {children}\r\n </a>\r\n );\r\n};\r\n\r\nexport default Anchor;","\r\nimport React from 'react';\r\n\r\n// Accordion component for collapsible content\r\ninterface AccordionProps {\r\n active: boolean;\r\n onClick: () => void;\r\n header: React.ReactNode;\r\n content: React.ReactNode;\r\n className?: string;\r\n containerClassName?: string;\r\n headerClassName?: string;\r\n contentClassName?: string;\r\n}\r\n\r\nconst Accordion = ({ active, onClick, header, content, className = '', containerClassName = 'border border-gray-200 rounded-lg overflow-hidden', headerClassName = 'w-full px-4 py-3 text-left bg-gray-50 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none transition-colors duration-200 flex justify-between items-center', contentClassName = 'transition-all duration-300 ease-in-out' }: AccordionProps) => {\r\n return (\r\n <div className={`${containerClassName} ${className}`}>\r\n <button\r\n onClick={onClick}\r\n className={headerClassName}\r\n aria-expanded={active}\r\n >\r\n {header}\r\n <svg\r\n className={`w-5 h-5 text-gray-500 transition-transform duration-200 ${active ? 'transform rotate-180' : ''\r\n }`}\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M19 9l-7 7-7-7\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <div\r\n className={`${contentClassName} ${active ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'\r\n } overflow-hidden`}\r\n >\r\n <div className={`p-4 bg-white border-t border-gray-200 ${contentClassName}`}>\r\n {content}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default Accordion;","import React from 'react';\n\ntype SpinnerSize = 'sm' | 'md' | 'lg';\ntype SpinnerType = 'circle' | 'dots' | 'pulse' | 'bars';\n\nexport interface SpinnerProps {\n className?: string;\n containerClassName?: string;\n dotClassName?: string;\n barClassName?: string;\n size?: SpinnerSize;\n type?: SpinnerType;\n};\n\nconst Spinner = ({\n className,\n containerClassName = 'flex gap-1',\n dotClassName = 'bg-blue-600 rounded-full animate-bounce',\n barClassName = 'bg-blue-600 animate-pulse',\n size = 'md',\n type = 'circle'\n}: SpinnerProps) => {\n const sizeClasses = {\n sm: 'w-4 h-4',\n md: 'w-6 h-6',\n lg: 'w-8 h-8'\n };\n\n const dotSizeClasses = {\n sm: 'w-1 h-1',\n md: 'w-2 h-2',\n lg: 'w-3 h-3'\n };\n\n const barSizeClasses = {\n sm: 'w-1 h-4',\n md: 'w-1 h-6',\n lg: 'w-1 h-8'\n };\n\n if (type === 'dots') {\n return (\n <div role=\"status\" className={`${containerClassName} ${className || ''}`}>\n <span className=\"sr-only\">Loading...</span>\n <div className={`${dotSizeClasses[size]} ${dotClassName}`} style={{ animationDelay: '0ms' }}></div>\n <div className={`${dotSizeClasses[size]} ${dotClassName}`} style={{ animationDelay: '150ms' }}></div>\n <div className={`${dotSizeClasses[size]} ${dotClassName}`} style={{ animationDelay: '300ms' }}></div>\n </div>\n );\n }\n\n if (type === 'pulse') {\n return (\n <div role=\"status\" className={`${sizeClasses[size]} ${className || ''}`}>\n <span className=\"sr-only\">Loading...</span>\n <div className={`${sizeClasses[size]} ${dotClassName}`}></div>\n </div>\n );\n }\n\n if (type === 'bars') {\n return (\n <div role=\"status\" className={`flex gap-1 items-center ${containerClassName} ${className || ''}`}>\n <span className=\"sr-only\">Loading...</span>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '0ms' }}></div>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '200ms' }}></div>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '400ms' }}></div>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '600ms' }}></div>\n </div>\n );\n }\n\n // Default circle spinner\n return (\n <div\n role=\"status\"\n className={`inline-block animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className || ''}`}\n >\n <span className=\"sr-only\">Loading...</span>\n </div>\n );\n};\n\nexport default Spinner;\n","{/* Dropdown component for selecting options */ }\r\nimport React, { useState } from 'react';\r\n\r\ntype DropDownOption = {\r\n value: string;\r\n label: React.ReactNode;\r\n};\r\n\r\ntype DropDownProps = {\r\n toggle: React.ReactNode;\r\n options: React.ReactNode[] | DropDownOption[];\r\n selected: React.ReactNode;\r\n onChange: (value: React.ReactNode) => void;\r\n className?: string;\r\n containerClassName?: string;\r\n dropdownClassName?: string;\r\n optionsContainerClassName?: string;\r\n optionClassName?: string;\r\n};\r\n\r\nconst DropDown = ({\r\n toggle,\r\n options,\r\n selected,\r\n onChange,\r\n className = '',\r\n containerClassName = 'relative inline-block text-left',\r\n dropdownClassName = 'absolute z-50 mt-2 w-48 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none',\r\n optionsContainerClassName = 'py-1 flex flex-col',\r\n optionClassName = 'block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:bg-gray-100 focus:text-gray-900'\r\n}: DropDownProps) => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n\r\n const handleToggle = () => {\r\n setIsOpen(!isOpen);\r\n };\r\n\r\n const handleOptionClick = (option: React.ReactNode) => {\r\n onChange(option);\r\n setIsOpen(false);\r\n };\r\n\r\n return (\r\n <div className={`${containerClassName} ${className}`}>\r\n <div onClick={handleToggle} className=\"cursor-pointer\">\r\n {toggle}\r\n </div>\r\n\r\n {isOpen && (\r\n <div className={dropdownClassName}>\r\n <div className={optionsContainerClassName}>\r\n {options.map((option, index) => {\r\n const isOptionObject = typeof option === 'object' && option !== null && 'value' in option;\r\n const optionValue = isOptionObject ? (option as DropDownOption).value : option;\r\n const optionLabel = isOptionObject ? (option as DropDownOption).label : option;\r\n\r\n return (\r\n <button\r\n key={index}\r\n onClick={() => handleOptionClick(optionValue)}\r\n className={optionClassName}\r\n >\r\n {optionLabel}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default DropDown;","import React from 'react';\r\n\r\n// Progress bar color variants\r\ntype ProgressBarVariant = 'primary' | 'success' | 'warning' | 'danger' | 'dark' | 'light';\r\n\r\n// Core progress bar props\r\ninterface ProgressBarProps {\r\n progress: number;\r\n max: number;\r\n min: number;\r\n 'aria-label': string;\r\n}\r\n\r\n// Extended props with styling options\r\ntype ProgressBarPropsWithClassName = ProgressBarProps & {\r\n className?: React.CSSProperties;\r\n style?: React.CSSProperties;\r\n containerClassName?: string;\r\n barClassName?: string;\r\n variant?: ProgressBarVariant;\r\n};\r\n\r\nconst ProgressBar = ({ progress, max, min, 'aria-label': ariaLabel, className, style, containerClassName = 'w-full bg-gray-200 rounded-full h-4 overflow-hidden', barClassName = 'h-full rounded-full transition-all duration-300 flex items-center justify-center text-xs font-medium', variant = 'primary' }: ProgressBarPropsWithClassName) => {\r\n const variantClasses = {\r\n primary: {\r\n bg: 'bg-blue-600',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-200'\r\n },\r\n success: {\r\n bg: 'bg-green-600',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-200'\r\n },\r\n warning: {\r\n bg: 'bg-yellow-500',\r\n text: 'text-gray-900',\r\n containerBg: 'bg-gray-200'\r\n },\r\n danger: {\r\n bg: 'bg-red-600',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-200'\r\n },\r\n dark: {\r\n bg: 'bg-gray-800',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-300'\r\n },\r\n light: {\r\n bg: 'bg-gray-100',\r\n text: 'text-gray-900',\r\n containerBg: 'bg-gray-300'\r\n }\r\n };\r\n\r\n const currentVariant = variantClasses[variant];\r\n const barClasses = `${currentVariant.bg} ${barClassName} ${currentVariant.text}`;\r\n\r\n return (\r\n <div className={containerClassName}>\r\n <div\r\n role=\"progressbar\"\r\n className={barClasses}\r\n aria-valuenow={progress}\r\n aria-valuemin={min}\r\n aria-valuemax={max}\r\n style={{ width: `${progress}%`, ...className, ...style }}\r\n >\r\n {progress > 10 && `${progress}%`}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default ProgressBar;","import React, { useState, useEffect, CSSProperties } from 'react';\r\n\r\n// Typing animation configuration\r\ntype TypedStyle = CSSProperties & {\r\n animation?: string;\r\n animationDelay?: string;\r\n};\r\n\r\ntype TypedProps = {\r\n strings: string[];\r\n typeSpeed?: number;\r\n backSpeed?: number;\r\n backDelay?: number;\r\n startDelay?: number;\r\n loop?: boolean;\r\n showCursor?: boolean;\r\n className?: string;\r\n containerClassName?: string;\r\n typedClassName?: string;\r\n cursorClassName?: string;\r\n style?: TypedStyle;\r\n};\r\n\r\nconst Typed = ({\r\n strings,\r\n typeSpeed = 50,\r\n backSpeed = 30,\r\n backDelay = 500,\r\n startDelay = 0,\r\n loop = true,\r\n showCursor = true,\r\n className = '',\r\n containerClassName = 'inline-block',\r\n typedClassName = 'typed',\r\n cursorClassName = 'typed-cursor ml-1 inline-block w-0.5 h-5 bg-current',\r\n style = {},\r\n}: TypedProps) => {\r\n const [currentStringIndex, setCurrentStringIndex] = useState(0);\r\n const [currentText, setCurrentText] = useState('');\r\n const [isDeleting, setIsDeleting] = useState(false);\r\n const [isPaused, setIsPaused] = useState(false);\r\n const [cursorOpacity, setCursorOpacity] = useState(1);\r\n\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setIsPaused(false);\r\n }, startDelay);\r\n\r\n return () => clearTimeout(timer);\r\n }, [startDelay]);\r\n\r\n useEffect(() => {\r\n if (isPaused) return;\r\n\r\n const currentString = strings[currentStringIndex] || '';\r\n\r\n const timer = setTimeout(() => {\r\n if (!isDeleting) {\r\n // Typing\r\n if (currentText.length < currentString.length) {\r\n setCurrentText(currentText + currentString[currentText.length]);\r\n } else {\r\n // Finished typing, wait before deleting\r\n if (loop) {\r\n setIsPaused(true);\r\n setTimeout(() => {\r\n setIsPaused(false);\r\n setIsDeleting(true);\r\n }, backDelay);\r\n }\r\n }\r\n } else {\r\n // Deleting\r\n if (currentText.length > 0) {\r\n setCurrentText(currentText.slice(0, -1));\r\n } else {\r\n // Finished deleting, move to next string\r\n setIsDeleting(false);\r\n setCurrentStringIndex((prevIndex) =>\r\n prevIndex === strings.length - 1 ? 0 : prevIndex + 1\r\n );\r\n }\r\n }\r\n }, isDeleting ? backSpeed : typeSpeed);\r\n\r\n return () => clearTimeout(timer);\r\n }, [currentText, isDeleting, currentStringIndex, strings, typeSpeed, backSpeed, backDelay, loop, isPaused]);\r\n\r\n // Cursor fade effect\r\n useEffect(() => {\r\n const fadeTimer = setInterval(() => {\r\n setCursorOpacity(prev => {\r\n if (prev === 1) return 0;\r\n return 1;\r\n });\r\n }, 750);\r\n\r\n return () => clearInterval(fadeTimer);\r\n }, []);\r\n\r\n return (\r\n <span className={`${containerClassName} ${className}`} >\r\n <span className={typedClassName}>{currentText}</span>\r\n {showCursor && (\r\n <span\r\n className={cursorClassName}\r\n aria-hidden=\"true\"\r\n style={{\r\n ...style,\r\n opacity: cursorOpacity\r\n }}\r\n >\r\n\r\n </span>\r\n )}\r\n </span>\r\n );\r\n};\r\n\r\nexport default Typed;","import React, { useEffect, useState } from 'react';\n\nexport interface PreloaderProps {\n /** Loading state - if true, preloader is shown */\n isLoading?: boolean;\n /** Duration in milliseconds before auto-hide */\n duration?: number;\n /** Background color overlay */\n backgroundColor?: string;\n /** Accent color for the spinner */\n accentColor?: string;\n /** Size of the spinner in pixels */\n size?: number;\n /** Border width of the spinner */\n borderWidth?: number;\n /** Custom className for the preloader */\n className?: string;\n /** Custom className for the spinner */\n spinnerClassName?: string;\n /** Custom z-index */\n zIndex?: number;\n /** Callback when preloader finishes */\n onComplete?: () => void;\n}\n\nconst Preloader = ({\n isLoading: externalLoading,\n duration = 1000,\n backgroundColor,\n accentColor,\n size = 90,\n borderWidth = 6,\n className = '',\n spinnerClassName = '',\n zIndex = 999999,\n onComplete\n}: PreloaderProps) => {\n const [internalLoading, setInternalLoading] = useState(true);\n\n // Use external loading state if provided, otherwise use internal state\n const isLoading = externalLoading !== undefined ? externalLoading : internalLoading;\n\n useEffect(() => {\n // Only auto-hide if we're using internal loading state\n if (externalLoading === undefined) {\n const timer = setTimeout(() => {\n setInternalLoading(false);\n onComplete?.();\n }, duration);\n\n return () => clearTimeout(timer);\n }\n }, [duration, externalLoading, onComplete]);\n\n // Handle external loading state changes - auto-hide when externalLoading is true\n useEffect(() => {\n if (externalLoading === true) {\n const timer = setTimeout(() => {\n onComplete?.();\n }, duration);\n\n return () => clearTimeout(timer);\n }\n }, [externalLoading, duration, onComplete]);\n\n const preloaderStyle: React.CSSProperties = {\n position: 'fixed',\n inset: 0,\n zIndex,\n overflow: 'hidden',\n background: backgroundColor || 'var(--background-color, #00000018)',\n transition: 'all 0.6s ease-out',\n display: isLoading ? 'block' : 'none'\n };\n\n const spinnerStyle: React.CSSProperties = {\n position: 'fixed',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n border: `${borderWidth}px solid #ffffff`,\n borderColor: `${accentColor || 'var(--accent-color, #007bff)'} transparent transparent transparent`,\n borderRadius: '50%',\n width: `${size}px`,\n height: `${size}px`,\n animation: 'animate-preloader 1.5s linear infinite'\n };\n\n return (\n <>\n <div\n className={`preloader-overlay ${className}`}\n style={preloaderStyle}\n >\n <div\n className={`preloader-spinner ${spinnerClassName}`}\n style={spinnerStyle}\n />\n </div>\n\n {/* Global styles for animation */}\n <style>{`\n @keyframes animate-preloader {\n 0% {\n transform: translate(-50%, -50%) rotate(0deg);\n }\n 100% {\n transform: translate(-50%, -50%) rotate(360deg);\n }\n }\n `}</style>\n </>\n );\n};\n\nexport default Preloader;\n","import React, { useEffect, useState, useRef } from 'react';\r\n\r\nexport interface ScrollTopProps {\r\n /** Scroll position threshold to show the button (in pixels) */\r\n threshold?: number;\r\n /** Custom className for the button */\r\n className?: string;\r\n /** Custom icon/content for the button */\r\n children?: React.ReactNode;\r\n /** Position of the button */\r\n position?: 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';\r\n /** Size of the button */\r\n size?: 'sm' | 'md' | 'lg';\r\n /** Shape of the button */\r\n shape?: 'circle' | 'square' | 'rounded';\r\n /** Whether to show the button initially */\r\n showInitially?: boolean;\r\n /** Custom scroll behavior */\r\n scrollBehavior?: 'auto' | 'smooth';\r\n /** Custom styles */\r\n style?: React.CSSProperties;\r\n /** Callback when button is clicked */\r\n onClick?: () => void;\r\n /** Callback when visibility changes */\r\n onVisibilityChange?: (isVisible: boolean) => void;\r\n /** Element ID or selector to check visibility for showing the button */\r\n targetElement?: string;\r\n /** Percentage of page scroll to show the button (0-100) */\r\n scrollPercentage?: number;\r\n}\r\n\r\nconst ScrollTop = ({\r\n threshold = 100,\r\n className = '',\r\n children,\r\n position = 'bottom-right',\r\n size = 'md',\r\n shape = 'circle',\r\n showInitially = false,\r\n scrollBehavior = 'smooth',\r\n style,\r\n onClick,\r\n onVisibilityChange,\r\n targetElement,\r\n scrollPercentage\r\n}: ScrollTopProps) => {\r\n const [isVisible, setIsVisible] = useState(showInitially);\r\n\r\n useEffect(() => {\r\n // Show/hide scroll to top button based on scroll position\r\n const toggleVisibility = () => {\r\n let shouldBeVisible = false;\r\n\r\n // Check scroll percentage first\r\n if (scrollPercentage !== undefined) {\r\n const maxScroll = document.documentElement.scrollHeight - window.innerHeight;\r\n const currentScroll = window.scrollY;\r\n const percentage = (currentScroll / maxScroll) * 100;\r\n shouldBeVisible = percentage >= scrollPercentage;\r\n }\r\n // Check target element visibility\r\n else if (targetElement) {\r\n const element = document.querySelector(targetElement);\r\n if (element) {\r\n const rect = element.getBoundingClientRect();\r\n const isInViewport = rect.top < window.innerHeight && rect.bottom > 0;\r\n shouldBeVisible = isInViewport; // Show when element is visible\r\n } else {\r\n // If element doesn't exist, fall back to threshold behavior\r\n shouldBeVisible = window.scrollY > threshold;\r\n }\r\n }\r\n // Default threshold behavior\r\n else {\r\n shouldBeVisible = window.scrollY > threshold;\r\n }\r\n\r\n // Set visibility immediately\r\n setIsVisible(shouldBeVisible);\r\n onVisibilityChange?.(shouldBeVisible);\r\n };\r\n\r\n window.addEventListener('scroll', toggleVisibility, { passive: true });\r\n // Initial check\r\n toggleVisibility();\r\n\r\n return () => {\r\n window.removeEventListener('scroll', toggleVisibility);\r\n };\r\n }, [threshold, onVisibilityChange, targetElement, scrollPercentage]);\r\n\r\n const scrollToTop = () => {\r\n window.scrollTo({\r\n top: 0,\r\n behavior: scrollBehavior\r\n });\r\n onClick?.();\r\n };\r\n\r\n const handleClick = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n scrollToTop();\r\n };\r\n\r\n // Position classes\r\n const positionClasses = {\r\n 'bottom-right': 'fixed bottom-8 right-8',\r\n 'bottom-left': 'fixed bottom-8 left-8',\r\n 'bottom-center': 'fixed bottom-8 left-1/2 transform -translate-x-1/2',\r\n 'top-right': 'fixed top-8 right-8',\r\n 'top-left': 'fixed top-8 left-8',\r\n 'top-center': 'fixed top-8 left-1/2 transform -translate-x-1/2'\r\n };\r\n\r\n // Size classes\r\n const sizeClasses = {\r\n sm: 'w-8 h-8 text-sm',\r\n md: 'w-12 h-12 text-base',\r\n lg: 'w-16 h-16 text-lg'\r\n };\r\n\r\n // Shape classes\r\n const shapeClasses = {\r\n circle: 'rounded-full',\r\n square: 'rounded-none',\r\n rounded: 'rounded-lg'\r\n };\r\n\r\n const buttonClasses = `\r\n ${positionClasses[position]}\r\n ${sizeClasses[size]}\r\n ${shapeClasses[shape]}\r\n ${className}\r\n flex items-center justify-center\r\n bg-blue-600 hover:bg-blue-700\r\n text-white\r\n shadow-lg hover:shadow-xl\r\n transition-all duration-300 ease-in-out\r\n cursor-pointer\r\n z-50\r\n ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4 pointer-events-none'}\r\n `;\r\n\r\n const defaultContent = (\r\n <svg\r\n className=\"w-4 h-4\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M5 10l7-7m0 0l7 7m-7-7v18\"\r\n />\r\n </svg>\r\n );\r\n\r\n return (\r\n <button\r\n className={buttonClasses}\r\n onClick={handleClick}\r\n style={style}\r\n aria-label=\"Scroll to top\"\r\n title=\"Scroll to top\"\r\n >\r\n {children || defaultContent}\r\n </button>\r\n );\r\n};\r\n\r\nexport default ScrollTop;\r\n","import React, { useState, useEffect } from 'react';\n\nexport interface WhatsAppProps {\n /** Phone number for WhatsApp (with country code, without + or spaces) */\n phone?: string;\n /** Default message to send */\n message?: string;\n /** Position of the button */\n position?: 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';\n /** Size of the button */\n size?: 'sm' | 'md' | 'lg';\n /** Show tooltip on hover */\n showTooltip?: boolean;\n /** Tooltip text */\n tooltipText?: string;\n /** Custom className for the button */\n className?: string;\n /** Custom styles */\n style?: React.CSSProperties;\n /** Callback when button is clicked */\n onClick?: () => void;\n /** Z-index for the button */\n zIndex?: number;\n /** Whether to open in new tab */\n openInNewTab?: boolean;\n}\n\nconst WhatsApp = ({\n phone = '',\n message = '¡Hola! Me gustaría obtener más información.',\n position = 'bottom-right',\n size = 'md',\n showTooltip = true,\n tooltipText = '¿En qué podemos ayudarte?',\n className = '',\n style,\n onClick,\n zIndex = 50,\n openInNewTab = true\n}: WhatsAppProps) => {\n const [isHovered, setIsHovered] = useState(false);\n\n // Don't render if no phone number provided\n if (!phone) return null;\n\n const handleWhatsAppClick = () => {\n const cleanPhone = phone.replace(/[^\\d]/g, '');\n const encodedMessage = encodeURIComponent(message);\n const whatsappUrl = `https://wa.me/${cleanPhone}?text=${encodedMessage}`;\n\n if (openInNewTab) {\n window.open(whatsappUrl, '_blank');\n } else {\n window.location.href = whatsappUrl;\n }\n\n onClick?.();\n };\n\n // Position classes\n const positionClasses = {\n 'bottom-right': 'bottom-6 right-6',\n 'bottom-left': 'bottom-6 left-6',\n 'bottom-center': 'bottom-6 left-1/2 transform -translate-x-1/2',\n 'top-right': 'top-6 right-6',\n 'top-left': 'top-6 left-6',\n 'top-center': 'top-6 left-1/2 transform -translate-x-1/2'\n };\n\n // Size classes\n const sizeClasses = {\n sm: 'w-10 h-10',\n md: 'w-14 h-14',\n lg: 'w-16 h-16'\n };\n\n // Icon size based on button size\n const iconSizes = {\n sm: 20,\n md: 32,\n lg: 40\n };\n\n const buttonClasses = `\n fixed ${positionClasses[position]}\n ${sizeClasses[size]}\n bg-[#25D366] hover:bg-[#128C7E]\n text-white rounded-full shadow-2xl\n flex items-center justify-center\n transition-all duration-300 hover:scale-110\n z-${zIndex}\n group\n ${className}\n `;\n\n return (\n <>\n <button\n className={buttonClasses}\n onClick={handleWhatsAppClick}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={style}\n aria-label=\"Chatear por WhatsApp\"\n title=\"Chatear por WhatsApp\"\n >\n <svg\n width={iconSizes[size]}\n height={iconSizes[size]}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\" />\n </svg>\n </button>\n\n {showTooltip && (\n <div\n className={`\n fixed ${positionClasses[position].replace('6', '20').replace('bottom-6', 'bottom-20').replace('top-6', 'top-20')}\n bg-white text-gray-800 px-3 py-1 rounded-md text-sm font-semibold\n shadow-md whitespace-nowrap pointer-events-none\n transition-opacity duration-300\n ${isHovered ? 'opacity-100' : 'opacity-0'}\n ${position.includes('right') ? 'right-20' : position.includes('left') ? 'left-20' : 'left-1/2 transform -translate-x-1/2'}\n `}\n style={{\n [position.includes('bottom') ? 'bottom' : 'top']: position.includes('bottom') ? '5.5rem' : '5.5rem'\n }}\n >\n {tooltipText}\n </div>\n )}\n </>\n );\n};\n\nexport default WhatsApp;\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"luna-components-library.js","names":[],"sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/jsx-runtime.js","../src/components/Button.tsx","../src/components/Card.tsx","../src/components/Anchor.tsx","../src/components/Accordion.tsx","../src/components/Spinner.tsx","../src/components/DropDown.tsx","../src/components/ProgressBar.tsx","../src/components/Typed.tsx","../src/components/Preloader.tsx","../src/components/ScrollTop.tsx","../src/components/WhatsApp.tsx","../src/components/Modal.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import React from 'react';\n\n// Button variants and sizes\ntype ButtonVariant = 'primary' | 'secondary' | 'outline';\ntype ButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps {\n children: React.ReactNode;\n variant?: ButtonVariant;\n size?: ButtonSize;\n onClick?: () => void;\n disabled?: boolean;\n className?: string;\n containerClassName?: string;\n variantClassName?: string;\n sizeClassName?: string;\n}\n\n{/* onCLick default should open window.open('https://andreychaconresumereact.netlify.app/', '_blank') */ }\n\nconst Button = ({\n children,\n variant = 'primary',\n size = 'sm',\n onClick = () =>\n void 0,\n disabled = false,\n className = '',\n containerClassName = 'font-medium rounded-lg transition-colors focus:outline-none focus:ring-2',\n variantClassName = 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',\n sizeClassName = 'px-3 py-1.5 text-sm'\n}: ButtonProps) => {\n const baseClasses = containerClassName;\n\n const variantClasses = {\n primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',\n secondary: 'bg-gray-600 text-white hover:bg-gray-700 focus:ring-gray-500',\n outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50 focus:ring-gray-500',\n };\n\n const sizeClasses = {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n };\n\n const classes = `\n ${baseClasses}\n ${variantClasses[variant]}\n ${sizeClasses[size]}\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${className}\n `.trim();\n\n return (\n <button\n className={classes}\n onClick={onClick}\n disabled={disabled}\n >\n {children}\n </button>\n );\n};\n\nexport default Button;\n","import React from 'react';\n\n// Card padding and shadow variants\ntype CardPadding = 'none' | 'sm' | 'md' | 'lg';\ntype CardShadow = 'none' | 'sm' | 'md' | 'lg';\n\nexport interface CardProps {\n children: React.ReactNode;\n title?: string;\n className?: string;\n containerClassName?: string;\n titleClassName?: string;\n padding?: CardPadding;\n shadow?: CardShadow;\n}\n\nconst Card = ({\n children,\n title,\n className = '',\n containerClassName = 'bg-white rounded-lg border border-gray-200',\n titleClassName = 'text-lg font-semibold text-gray-900',\n padding = 'md',\n shadow = 'md',\n}: CardProps) => {\n const paddingClasses = {\n none: '',\n sm: 'p-3',\n md: 'p-4',\n lg: 'p-6',\n };\n\n const shadowClasses = {\n none: '',\n sm: 'shadow-sm',\n md: 'shadow-md',\n lg: 'shadow-lg',\n };\n\n const classes = `\n ${containerClassName}\n ${paddingClasses[padding]}\n ${shadowClasses[shadow]}\n ${className}\n `.trim();\n\n return (\n <div className={classes}>\n {title && (\n <div className=\"mb-4\">\n <h3 className={titleClassName}>{title}</h3>\n </div>\n )}\n {children}\n </div>\n );\n};\n\nexport default Card;\n","import React from 'react';\r\n\r\n// Anchor link variants and sizes\r\ntype AnchorVariant = 'none' | 'primary' | 'secondary' | 'outline';\r\ntype AnchorSize = 'sm' | 'md' | 'lg';\r\n\r\nexport interface AnchorProps {\r\n children?: React.ReactNode;\r\n variant?: AnchorVariant;\r\n size?: AnchorSize;\r\n href?: string;\r\n className?: string;\r\n containerClassName?: string;\r\n variantClassName?: string;\r\n sizeClassName?: string;\r\n target?: string;\r\n rel?: string;\r\n}\r\n\r\nconst Anchor = ({\r\n children = \"Pablo Andrey Chacon Luna\",\r\n variant = 'none',\r\n size = 'sm',\r\n href = 'https://andreychaconresumereact.netlify.app/',\r\n className,\r\n containerClassName = 'font-medium rounded-lg transition-colors focus:outline-none focus:ring-2',\r\n variantClassName = 'bg-blue-600 text-white hover:bg-blue-700',\r\n sizeClassName = 'px-3 py-1.5 text-sm',\r\n target = '_blank',\r\n rel = 'noopener noreferrer'\r\n}: AnchorProps) => {\r\n\r\n const baseClasses = containerClassName;\r\n\r\n const variantClasses = {\r\n none: '',\r\n primary: 'bg-blue-600 text-white hover:bg-blue-700',\r\n secondary: 'bg-gray-600 text-white hover:bg-gray-700',\r\n outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50',\r\n };\r\n\r\n const sizeClasses = {\r\n sm: 'px-3 py-1.5 text-sm',\r\n md: 'px-4 py-2 text-base',\r\n lg: 'px-6 py-3 text-lg',\r\n };\r\n\r\n const classes = `\r\n ${baseClasses}\r\n ${variantClasses[variant]}\r\n ${sizeClasses[size]}\r\n ${variantClassName}\r\n ${sizeClassName}\r\n ${className}\r\n `.trim();\r\n\r\n return (\r\n <a href={href} target={target} rel={rel} className={classes}>\r\n {children}\r\n </a>\r\n );\r\n};\r\n\r\nexport default Anchor;","\r\nimport React from 'react';\r\n\r\n// Accordion component for collapsible content\r\ninterface AccordionProps {\r\n active: boolean;\r\n onClick: () => void;\r\n header: React.ReactNode;\r\n content: React.ReactNode;\r\n className?: string;\r\n containerClassName?: string;\r\n headerClassName?: string;\r\n contentClassName?: string;\r\n}\r\n\r\nconst Accordion = ({ active, onClick, header, content, className = '', containerClassName = 'border border-gray-200 rounded-lg overflow-hidden', headerClassName = 'w-full px-4 py-3 text-left bg-gray-50 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none transition-colors duration-200 flex justify-between items-center', contentClassName = 'transition-all duration-300 ease-in-out' }: AccordionProps) => {\r\n return (\r\n <div className={`${containerClassName} ${className}`}>\r\n <button\r\n onClick={onClick}\r\n className={headerClassName}\r\n aria-expanded={active}\r\n >\r\n {header}\r\n <svg\r\n className={`w-5 h-5 text-gray-500 transition-transform duration-200 ${active ? 'transform rotate-180' : ''\r\n }`}\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M19 9l-7 7-7-7\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <div\r\n className={`${contentClassName} ${active ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'\r\n } overflow-hidden`}\r\n >\r\n <div className={`p-4 bg-white border-t border-gray-200 ${contentClassName}`}>\r\n {content}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default Accordion;","import React from 'react';\n\ntype SpinnerSize = 'sm' | 'md' | 'lg';\ntype SpinnerType = 'circle' | 'dots' | 'pulse' | 'bars';\n\nexport interface SpinnerProps {\n className?: string;\n containerClassName?: string;\n dotClassName?: string;\n barClassName?: string;\n size?: SpinnerSize;\n type?: SpinnerType;\n};\n\nconst Spinner = ({\n className,\n containerClassName = 'flex gap-1',\n dotClassName = 'bg-blue-600 rounded-full animate-bounce',\n barClassName = 'bg-blue-600 animate-pulse',\n size = 'md',\n type = 'circle'\n}: SpinnerProps) => {\n const sizeClasses = {\n sm: 'w-4 h-4',\n md: 'w-6 h-6',\n lg: 'w-8 h-8'\n };\n\n const dotSizeClasses = {\n sm: 'w-1 h-1',\n md: 'w-2 h-2',\n lg: 'w-3 h-3'\n };\n\n const barSizeClasses = {\n sm: 'w-1 h-4',\n md: 'w-1 h-6',\n lg: 'w-1 h-8'\n };\n\n if (type === 'dots') {\n return (\n <div role=\"status\" className={`${containerClassName} ${className || ''}`}>\n <span className=\"sr-only\">Loading...</span>\n <div className={`${dotSizeClasses[size]} ${dotClassName}`} style={{ animationDelay: '0ms' }}></div>\n <div className={`${dotSizeClasses[size]} ${dotClassName}`} style={{ animationDelay: '150ms' }}></div>\n <div className={`${dotSizeClasses[size]} ${dotClassName}`} style={{ animationDelay: '300ms' }}></div>\n </div>\n );\n }\n\n if (type === 'pulse') {\n return (\n <div role=\"status\" className={`${sizeClasses[size]} ${className || ''}`}>\n <span className=\"sr-only\">Loading...</span>\n <div className={`${sizeClasses[size]} ${dotClassName}`}></div>\n </div>\n );\n }\n\n if (type === 'bars') {\n return (\n <div role=\"status\" className={`flex gap-1 items-center ${containerClassName} ${className || ''}`}>\n <span className=\"sr-only\">Loading...</span>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '0ms' }}></div>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '200ms' }}></div>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '400ms' }}></div>\n <div className={`${barSizeClasses[size]} ${barClassName}`} style={{ animationDelay: '600ms' }}></div>\n </div>\n );\n }\n\n // Default circle spinner\n return (\n <div\n role=\"status\"\n className={`inline-block animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className || ''}`}\n >\n <span className=\"sr-only\">Loading...</span>\n </div>\n );\n};\n\nexport default Spinner;\n","{/* Dropdown component for selecting options */ }\r\nimport React, { useState } from 'react';\r\n\r\ntype DropDownOption = {\r\n value: string;\r\n label: React.ReactNode;\r\n};\r\n\r\ntype DropDownProps = {\r\n toggle: React.ReactNode;\r\n options: React.ReactNode[] | DropDownOption[];\r\n selected: React.ReactNode;\r\n onChange: (value: React.ReactNode) => void;\r\n className?: string;\r\n containerClassName?: string;\r\n dropdownClassName?: string;\r\n optionsContainerClassName?: string;\r\n optionClassName?: string;\r\n};\r\n\r\nconst DropDown = ({\r\n toggle,\r\n options,\r\n selected,\r\n onChange,\r\n className = '',\r\n containerClassName = 'relative inline-block text-left',\r\n dropdownClassName = 'absolute z-50 mt-2 w-48 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none',\r\n optionsContainerClassName = 'py-1 flex flex-col',\r\n optionClassName = 'block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:bg-gray-100 focus:text-gray-900'\r\n}: DropDownProps) => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n\r\n const handleToggle = () => {\r\n setIsOpen(!isOpen);\r\n };\r\n\r\n const handleOptionClick = (option: React.ReactNode) => {\r\n onChange(option);\r\n setIsOpen(false);\r\n };\r\n\r\n return (\r\n <div className={`${containerClassName} ${className}`}>\r\n <div onClick={handleToggle} className=\"cursor-pointer\">\r\n {toggle}\r\n </div>\r\n\r\n {isOpen && (\r\n <div className={dropdownClassName}>\r\n <div className={optionsContainerClassName}>\r\n {options.map((option, index) => {\r\n const isOptionObject = typeof option === 'object' && option !== null && 'value' in option;\r\n const optionValue = isOptionObject ? (option as DropDownOption).value : option;\r\n const optionLabel = isOptionObject ? (option as DropDownOption).label : option;\r\n\r\n return (\r\n <button\r\n key={index}\r\n onClick={() => handleOptionClick(optionValue)}\r\n className={optionClassName}\r\n >\r\n {optionLabel}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default DropDown;","import React from 'react';\r\n\r\n// Progress bar color variants\r\ntype ProgressBarVariant = 'primary' | 'success' | 'warning' | 'danger' | 'dark' | 'light';\r\n\r\n// Core progress bar props\r\ninterface ProgressBarProps {\r\n progress: number;\r\n max: number;\r\n min: number;\r\n 'aria-label': string;\r\n}\r\n\r\n// Extended props with styling options\r\ntype ProgressBarPropsWithClassName = ProgressBarProps & {\r\n className?: React.CSSProperties;\r\n style?: React.CSSProperties;\r\n containerClassName?: string;\r\n barClassName?: string;\r\n variant?: ProgressBarVariant;\r\n};\r\n\r\nconst ProgressBar = ({ progress, max, min, 'aria-label': ariaLabel, className, style, containerClassName = 'w-full bg-gray-200 rounded-full h-4 overflow-hidden', barClassName = 'h-full rounded-full transition-all duration-300 flex items-center justify-center text-xs font-medium', variant = 'primary' }: ProgressBarPropsWithClassName) => {\r\n const variantClasses = {\r\n primary: {\r\n bg: 'bg-blue-600',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-200'\r\n },\r\n success: {\r\n bg: 'bg-green-600',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-200'\r\n },\r\n warning: {\r\n bg: 'bg-yellow-500',\r\n text: 'text-gray-900',\r\n containerBg: 'bg-gray-200'\r\n },\r\n danger: {\r\n bg: 'bg-red-600',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-200'\r\n },\r\n dark: {\r\n bg: 'bg-gray-800',\r\n text: 'text-white',\r\n containerBg: 'bg-gray-300'\r\n },\r\n light: {\r\n bg: 'bg-gray-100',\r\n text: 'text-gray-900',\r\n containerBg: 'bg-gray-300'\r\n }\r\n };\r\n\r\n const currentVariant = variantClasses[variant];\r\n const barClasses = `${currentVariant.bg} ${barClassName} ${currentVariant.text}`;\r\n\r\n return (\r\n <div className={containerClassName}>\r\n <div\r\n role=\"progressbar\"\r\n className={barClasses}\r\n aria-valuenow={progress}\r\n aria-valuemin={min}\r\n aria-valuemax={max}\r\n style={{ width: `${progress}%`, ...className, ...style }}\r\n >\r\n {progress > 10 && `${progress}%`}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default ProgressBar;","import React, { useState, useEffect, CSSProperties } from 'react';\r\n\r\n// Typing animation configuration\r\ntype TypedStyle = CSSProperties & {\r\n animation?: string;\r\n animationDelay?: string;\r\n};\r\n\r\ntype TypedProps = {\r\n strings: string[];\r\n typeSpeed?: number;\r\n backSpeed?: number;\r\n backDelay?: number;\r\n startDelay?: number;\r\n loop?: boolean;\r\n showCursor?: boolean;\r\n className?: string;\r\n containerClassName?: string;\r\n typedClassName?: string;\r\n cursorClassName?: string;\r\n style?: TypedStyle;\r\n};\r\n\r\nconst Typed = ({\r\n strings,\r\n typeSpeed = 50,\r\n backSpeed = 30,\r\n backDelay = 500,\r\n startDelay = 0,\r\n loop = true,\r\n showCursor = true,\r\n className = '',\r\n containerClassName = 'inline-block',\r\n typedClassName = 'typed',\r\n cursorClassName = 'typed-cursor ml-1 inline-block w-0.5 h-5 bg-current',\r\n style = {},\r\n}: TypedProps) => {\r\n const [currentStringIndex, setCurrentStringIndex] = useState(0);\r\n const [currentText, setCurrentText] = useState('');\r\n const [isDeleting, setIsDeleting] = useState(false);\r\n const [isPaused, setIsPaused] = useState(false);\r\n const [cursorOpacity, setCursorOpacity] = useState(1);\r\n\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setIsPaused(false);\r\n }, startDelay);\r\n\r\n return () => clearTimeout(timer);\r\n }, [startDelay]);\r\n\r\n useEffect(() => {\r\n if (isPaused) return;\r\n\r\n const currentString = strings[currentStringIndex] || '';\r\n\r\n const timer = setTimeout(() => {\r\n if (!isDeleting) {\r\n // Typing\r\n if (currentText.length < currentString.length) {\r\n setCurrentText(currentText + currentString[currentText.length]);\r\n } else {\r\n // Finished typing, wait before deleting\r\n if (loop) {\r\n setIsPaused(true);\r\n setTimeout(() => {\r\n setIsPaused(false);\r\n setIsDeleting(true);\r\n }, backDelay);\r\n }\r\n }\r\n } else {\r\n // Deleting\r\n if (currentText.length > 0) {\r\n setCurrentText(currentText.slice(0, -1));\r\n } else {\r\n // Finished deleting, move to next string\r\n setIsDeleting(false);\r\n setCurrentStringIndex((prevIndex) =>\r\n prevIndex === strings.length - 1 ? 0 : prevIndex + 1\r\n );\r\n }\r\n }\r\n }, isDeleting ? backSpeed : typeSpeed);\r\n\r\n return () => clearTimeout(timer);\r\n }, [currentText, isDeleting, currentStringIndex, strings, typeSpeed, backSpeed, backDelay, loop, isPaused]);\r\n\r\n // Cursor fade effect\r\n useEffect(() => {\r\n const fadeTimer = setInterval(() => {\r\n setCursorOpacity(prev => {\r\n if (prev === 1) return 0;\r\n return 1;\r\n });\r\n }, 750);\r\n\r\n return () => clearInterval(fadeTimer);\r\n }, []);\r\n\r\n return (\r\n <span className={`${containerClassName} ${className}`} >\r\n <span className={typedClassName}>{currentText}</span>\r\n {showCursor && (\r\n <span\r\n className={cursorClassName}\r\n aria-hidden=\"true\"\r\n style={{\r\n ...style,\r\n opacity: cursorOpacity\r\n }}\r\n >\r\n\r\n </span>\r\n )}\r\n </span>\r\n );\r\n};\r\n\r\nexport default Typed;","import React, { useEffect, useState } from 'react';\n\nexport interface PreloaderProps {\n /** Loading state - if true, preloader is shown */\n isLoading?: boolean;\n /** Duration in milliseconds before auto-hide */\n duration?: number;\n /** Background color overlay */\n backgroundColor?: string;\n /** Accent color for the spinner */\n accentColor?: string;\n /** Size of the spinner in pixels */\n size?: number;\n /** Border width of the spinner */\n borderWidth?: number;\n /** Custom className for the preloader */\n className?: string;\n /** Custom className for the spinner */\n spinnerClassName?: string;\n /** Custom z-index */\n zIndex?: number;\n /** Callback when preloader finishes */\n onComplete?: () => void;\n}\n\nconst Preloader = ({\n isLoading: externalLoading,\n duration = 1000,\n backgroundColor,\n accentColor,\n size = 90,\n borderWidth = 6,\n className = '',\n spinnerClassName = '',\n zIndex = 999999,\n onComplete\n}: PreloaderProps) => {\n const [internalLoading, setInternalLoading] = useState(true);\n\n // Use external loading state if provided, otherwise use internal state\n const isLoading = externalLoading !== undefined ? externalLoading : internalLoading;\n\n useEffect(() => {\n // Only auto-hide if we're using internal loading state\n if (externalLoading === undefined) {\n const timer = setTimeout(() => {\n setInternalLoading(false);\n onComplete?.();\n }, duration);\n\n return () => clearTimeout(timer);\n }\n }, [duration, externalLoading, onComplete]);\n\n // Handle external loading state changes - auto-hide when externalLoading is true\n useEffect(() => {\n if (externalLoading === true) {\n const timer = setTimeout(() => {\n onComplete?.();\n }, duration);\n\n return () => clearTimeout(timer);\n }\n }, [externalLoading, duration, onComplete]);\n\n const preloaderStyle: React.CSSProperties = {\n position: 'fixed',\n inset: 0,\n zIndex,\n overflow: 'hidden',\n background: backgroundColor || 'var(--background-color, #00000018)',\n transition: 'all 0.6s ease-out',\n display: isLoading ? 'block' : 'none'\n };\n\n const spinnerStyle: React.CSSProperties = {\n position: 'fixed',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n border: `${borderWidth}px solid #ffffff`,\n borderColor: `${accentColor || 'var(--accent-color, #007bff)'} transparent transparent transparent`,\n borderRadius: '50%',\n width: `${size}px`,\n height: `${size}px`,\n animation: 'animate-preloader 1.5s linear infinite'\n };\n\n return (\n <>\n <div\n className={`preloader-overlay ${className}`}\n style={preloaderStyle}\n >\n <div\n className={`preloader-spinner ${spinnerClassName}`}\n style={spinnerStyle}\n />\n </div>\n\n {/* Global styles for animation */}\n <style>{`\n @keyframes animate-preloader {\n 0% {\n transform: translate(-50%, -50%) rotate(0deg);\n }\n 100% {\n transform: translate(-50%, -50%) rotate(360deg);\n }\n }\n `}</style>\n </>\n );\n};\n\nexport default Preloader;\n","import React, { useEffect, useState, useRef } from 'react';\r\n\r\nexport interface ScrollTopProps {\r\n /** Scroll position threshold to show the button (in pixels) */\r\n threshold?: number;\r\n /** Custom className for the button */\r\n className?: string;\r\n /** Custom icon/content for the button */\r\n children?: React.ReactNode;\r\n /** Position of the button */\r\n position?: 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';\r\n /** Size of the button */\r\n size?: 'sm' | 'md' | 'lg';\r\n /** Shape of the button */\r\n shape?: 'circle' | 'square' | 'rounded';\r\n /** Whether to show the button initially */\r\n showInitially?: boolean;\r\n /** Custom scroll behavior */\r\n scrollBehavior?: 'auto' | 'smooth';\r\n /** Custom styles */\r\n style?: React.CSSProperties;\r\n /** Callback when button is clicked */\r\n onClick?: () => void;\r\n /** Callback when visibility changes */\r\n onVisibilityChange?: (isVisible: boolean) => void;\r\n /** Element ID or selector to check visibility for showing the button */\r\n targetElement?: string;\r\n /** Percentage of page scroll to show the button (0-100) */\r\n scrollPercentage?: number;\r\n}\r\n\r\nconst ScrollTop = ({\r\n threshold = 100,\r\n className = '',\r\n children,\r\n position = 'bottom-right',\r\n size = 'md',\r\n shape = 'circle',\r\n showInitially = false,\r\n scrollBehavior = 'smooth',\r\n style,\r\n onClick,\r\n onVisibilityChange,\r\n targetElement,\r\n scrollPercentage\r\n}: ScrollTopProps) => {\r\n const [isVisible, setIsVisible] = useState(showInitially);\r\n\r\n useEffect(() => {\r\n // Show/hide scroll to top button based on scroll position\r\n const toggleVisibility = () => {\r\n let shouldBeVisible = false;\r\n\r\n // Check scroll percentage first\r\n if (scrollPercentage !== undefined) {\r\n const maxScroll = document.documentElement.scrollHeight - window.innerHeight;\r\n const currentScroll = window.scrollY;\r\n const percentage = (currentScroll / maxScroll) * 100;\r\n shouldBeVisible = percentage >= scrollPercentage;\r\n }\r\n // Check target element visibility\r\n else if (targetElement) {\r\n const element = document.querySelector(targetElement);\r\n if (element) {\r\n const rect = element.getBoundingClientRect();\r\n const isInViewport = rect.top < window.innerHeight && rect.bottom > 0;\r\n shouldBeVisible = isInViewport; // Show when element is visible\r\n } else {\r\n // If element doesn't exist, fall back to threshold behavior\r\n shouldBeVisible = window.scrollY > threshold;\r\n }\r\n }\r\n // Default threshold behavior\r\n else {\r\n shouldBeVisible = window.scrollY > threshold;\r\n }\r\n\r\n // Set visibility immediately\r\n setIsVisible(shouldBeVisible);\r\n onVisibilityChange?.(shouldBeVisible);\r\n };\r\n\r\n window.addEventListener('scroll', toggleVisibility, { passive: true });\r\n // Initial check\r\n toggleVisibility();\r\n\r\n return () => {\r\n window.removeEventListener('scroll', toggleVisibility);\r\n };\r\n }, [threshold, onVisibilityChange, targetElement, scrollPercentage]);\r\n\r\n const scrollToTop = () => {\r\n window.scrollTo({\r\n top: 0,\r\n behavior: scrollBehavior\r\n });\r\n onClick?.();\r\n };\r\n\r\n const handleClick = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n scrollToTop();\r\n };\r\n\r\n // Position classes\r\n const positionClasses = {\r\n 'bottom-right': 'fixed bottom-8 right-8',\r\n 'bottom-left': 'fixed bottom-8 left-8',\r\n 'bottom-center': 'fixed bottom-8 left-1/2 transform -translate-x-1/2',\r\n 'top-right': 'fixed top-8 right-8',\r\n 'top-left': 'fixed top-8 left-8',\r\n 'top-center': 'fixed top-8 left-1/2 transform -translate-x-1/2'\r\n };\r\n\r\n // Size classes\r\n const sizeClasses = {\r\n sm: 'w-8 h-8 text-sm',\r\n md: 'w-12 h-12 text-base',\r\n lg: 'w-16 h-16 text-lg'\r\n };\r\n\r\n // Shape classes\r\n const shapeClasses = {\r\n circle: 'rounded-full',\r\n square: 'rounded-none',\r\n rounded: 'rounded-lg'\r\n };\r\n\r\n const buttonClasses = `\r\n ${positionClasses[position]}\r\n ${sizeClasses[size]}\r\n ${shapeClasses[shape]}\r\n ${className}\r\n flex items-center justify-center\r\n bg-blue-600 hover:bg-blue-700\r\n text-white\r\n shadow-lg hover:shadow-xl\r\n transition-all duration-300 ease-in-out\r\n cursor-pointer\r\n z-50\r\n ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4 pointer-events-none'}\r\n `;\r\n\r\n const defaultContent = (\r\n <svg\r\n className=\"w-4 h-4\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M5 10l7-7m0 0l7 7m-7-7v18\"\r\n />\r\n </svg>\r\n );\r\n\r\n return (\r\n <button\r\n className={buttonClasses}\r\n onClick={handleClick}\r\n style={style}\r\n aria-label=\"Scroll to top\"\r\n title=\"Scroll to top\"\r\n >\r\n {children || defaultContent}\r\n </button>\r\n );\r\n};\r\n\r\nexport default ScrollTop;\r\n","import React, { useState, useEffect } from 'react';\n\nexport interface WhatsAppProps {\n /** Phone number for WhatsApp (with country code, without + or spaces) */\n phone?: string;\n /** Default message to send */\n message?: string;\n /** Position of the button */\n position?: 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';\n /** Size of the button */\n size?: 'sm' | 'md' | 'lg';\n /** Show tooltip on hover */\n showTooltip?: boolean;\n /** Tooltip text */\n tooltipText?: string;\n /** Custom className for the button */\n className?: string;\n /** Custom className for the tooltip */\n tooltipClassName?: string;\n /** Custom styles */\n style?: React.CSSProperties;\n /** Callback when button is clicked */\n onClick?: () => void;\n /** Z-index for the button */\n zIndex?: number;\n /** Whether to open in new tab */\n openInNewTab?: boolean;\n}\n\nconst WhatsApp = ({\n phone = '',\n message = '¡Hola! Me gustaría obtener más información.',\n position = 'bottom-right',\n size = 'md',\n showTooltip = true,\n tooltipText = '¿En qué podemos ayudarte?',\n className = '',\n tooltipClassName = '',\n style,\n onClick,\n zIndex = 50,\n openInNewTab = true\n}: WhatsAppProps) => {\n const [isHovered, setIsHovered] = useState(false);\n\n // Don't render if no phone number provided\n if (!phone) return null;\n\n const handleWhatsAppClick = () => {\n const cleanPhone = phone.replace(/[^\\d]/g, '');\n const encodedMessage = encodeURIComponent(message);\n const whatsappUrl = `https://wa.me/${cleanPhone}?text=${encodedMessage}`;\n\n if (openInNewTab) {\n window.open(whatsappUrl, '_blank');\n } else {\n window.location.href = whatsappUrl;\n }\n\n onClick?.();\n };\n\n // Position classes\n const positionClasses = {\n 'bottom-right': 'bottom-6 right-6',\n 'bottom-left': 'bottom-6 left-6',\n 'bottom-center': 'bottom-6 left-1/2 transform -translate-x-1/2',\n 'top-right': 'top-6 right-6',\n 'top-left': 'top-6 left-6',\n 'top-center': 'top-6 left-1/2 transform -translate-x-1/2'\n };\n\n // Size classes\n const sizeClasses = {\n sm: 'w-10 h-10',\n md: 'w-14 h-14',\n lg: 'w-16 h-16'\n };\n\n // Icon size based on button size\n const iconSizes = {\n sm: 20,\n md: 32,\n lg: 40\n };\n\n const buttonClasses = `\n fixed ${positionClasses[position]}\n ${sizeClasses[size]}\n bg-[#25D366] hover:bg-[#128C7E]\n text-white rounded-full shadow-2xl\n flex items-center justify-center\n transition-all duration-300 hover:scale-110\n z-${zIndex}\n group\n ${className}\n `;\n\n return (\n <>\n <button\n className={buttonClasses}\n onClick={handleWhatsAppClick}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={style}\n aria-label=\"Chatear por WhatsApp\"\n title=\"Chatear por WhatsApp\"\n >\n <svg\n width={iconSizes[size]}\n height={iconSizes[size]}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\" />\n </svg>\n </button>\n\n {showTooltip && (\n <div\n className={`\n fixed ${positionClasses[position].replace('6', '20').replace('bottom-6', 'bottom-20').replace('top-6', 'top-20')}\n bg-white text-gray-800 px-3 py-1 rounded-md text-sm font-semibold\n shadow-md whitespace-nowrap pointer-events-none\n transition-opacity duration-300\n ${isHovered ? 'opacity-100' : 'opacity-0'}\n ${position.includes('right') ? 'right-20' : position.includes('left') ? 'left-20' : 'left-1/2 transform -translate-x-1/2'}\n ${tooltipClassName}\n `}\n style={{\n [position.includes('bottom') ? 'bottom' : 'top']: position.includes('bottom') ? '5.5rem' : '5.5rem'\n }}\n >\n {tooltipText}\n </div>\n )}\n </>\n );\n};\n\nexport default WhatsApp;\n","import React, { useEffect, useRef } from 'react';\n\n// Modal size variants\ntype ModalSize = 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface ModalProps {\n /** Whether the modal is visible */\n show: boolean;\n /** Callback when modal is closed */\n onHide: () => void;\n /** Modal size variant */\n size?: ModalSize;\n /** Whether to center the modal vertically */\n centered?: boolean;\n /** Whether to show backdrop overlay */\n backdrop?: boolean | 'static';\n /** Whether to close modal when backdrop is clicked */\n backdropClose?: boolean;\n /** Whether to close modal when ESC key is pressed */\n keyboard?: boolean;\n /** Whether to show modal with animation */\n animation?: boolean;\n /** Custom className for the modal */\n className?: string;\n /** Custom className for the modal dialog */\n dialogClassName?: string;\n /** Custom className for the modal content */\n contentClassName?: string;\n /** Custom className for the modal header */\n headerClassName?: string;\n /** Custom className for the modal body */\n bodyClassName?: string;\n /** Custom className for the modal footer */\n footerClassName?: string;\n /** Modal title */\n title?: React.ReactNode;\n /** Modal header content */\n header?: React.ReactNode;\n /** Modal body content */\n children: React.ReactNode;\n /** Modal footer content */\n footer?: React.ReactNode;\n /** Whether to show close button in header */\n closeButton?: boolean;\n}\n\nconst Modal = ({\n show,\n onHide,\n size = 'md',\n centered = false,\n backdrop = true,\n backdropClose = true,\n keyboard = true,\n animation = true,\n className = '',\n dialogClassName = '',\n contentClassName = '',\n headerClassName = '',\n bodyClassName = '',\n footerClassName = '',\n title,\n header,\n children,\n footer,\n closeButton = true\n}: ModalProps) => {\n const modalRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n\n // Handle ESC key press\n useEffect(() => {\n if (!show || !keyboard) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onHide();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [show, keyboard, onHide]);\n\n // Handle backdrop click\n const handleBackdropClick = (event: React.MouseEvent) => {\n if (backdropClose) {\n // Check if click is on backdrop using data attribute\n const target = event.target as HTMLElement;\n if (target.getAttribute('data-backdrop') === 'true' || target.closest('[data-backdrop=\"true\"]')) {\n onHide();\n }\n }\n };\n\n // Focus management\n useEffect(() => {\n if (show) {\n previousActiveElement.current = document.activeElement as HTMLElement;\n // Focus the modal dialog\n if (modalRef.current) {\n modalRef.current.focus();\n }\n // Prevent body scroll\n document.body.style.overflow = 'hidden';\n } else {\n // Restore focus and body scroll\n if (previousActiveElement.current) {\n previousActiveElement.current.focus();\n }\n document.body.style.overflow = '';\n }\n\n return () => {\n document.body.style.overflow = '';\n };\n }, [show]);\n\n // Size classes\n const sizeClasses = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl'\n };\n\n const modalClasses = `\n fixed inset-0 z-60 flex items-center justify-center\n ${show ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}\n ${animation ? 'transition-opacity duration-300' : ''}\n ${className}\n `.trim();\n\n const dialogClasses = `\n relative w-full ${sizeClasses[size]} mx-auto\n ${centered ? 'flex items-center justify-center min-h-screen' : 'mt-8'}\n ${dialogClassName}\n `.trim();\n\n if (!show) return null;\n\n return (\n <div\n ref={modalRef}\n className={modalClasses}\n tabIndex={-1}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? 'modal-title' : undefined}\n >\n {/* Backdrop */}\n {backdrop && (\n <div\n data-backdrop=\"true\"\n className={`absolute inset-0 bg-black bg-opacity-50 ${animation ? 'transition-opacity duration-300' : ''} ${show ? 'opacity-100' : 'opacity-0'}`}\n onClick={handleBackdropClick}\n />\n )}\n\n {/* Modal Content */}\n <div className={dialogClasses}>\n <div className={`bg-white rounded-lg shadow-xl relative z-10 ${contentClassName}`}>\n {/* Modal Header */}\n {(header || title || closeButton) && (\n <div className={`flex items-center justify-between p-4 border-b border-gray-200 ${headerClassName}`}>\n {header || (title && (\n <h3 className=\"text-lg font-semibold text-gray-900\" id=\"modal-title\">\n {title}\n </h3>\n ))}\n {closeButton && (\n <button\n type=\"button\"\n className=\"text-gray-400 hover:text-gray-600 transition-colors\"\n onClick={onHide}\n aria-label=\"Close\"\n >\n <svg className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n )}\n\n {/* Modal Body */}\n <div className={`p-4 ${bodyClassName}`}>\n {children}\n </div>\n\n {/* Modal Footer */}\n {footer && (\n <div className={`flex items-center justify-end p-4 border-t border-gray-200 space-x-2 ${footerClassName}`}>\n {footer}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default Modal;\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
3
|
+
export interface ModalProps {
|
|
4
|
+
/** Whether the modal is visible */
|
|
5
|
+
show: boolean;
|
|
6
|
+
/** Callback when modal is closed */
|
|
7
|
+
onHide: () => void;
|
|
8
|
+
/** Modal size variant */
|
|
9
|
+
size?: ModalSize;
|
|
10
|
+
/** Whether to center the modal vertically */
|
|
11
|
+
centered?: boolean;
|
|
12
|
+
/** Whether to show backdrop overlay */
|
|
13
|
+
backdrop?: boolean | 'static';
|
|
14
|
+
/** Whether to close modal when backdrop is clicked */
|
|
15
|
+
backdropClose?: boolean;
|
|
16
|
+
/** Whether to close modal when ESC key is pressed */
|
|
17
|
+
keyboard?: boolean;
|
|
18
|
+
/** Whether to show modal with animation */
|
|
19
|
+
animation?: boolean;
|
|
20
|
+
/** Custom className for the modal */
|
|
21
|
+
className?: string;
|
|
22
|
+
/** Custom className for the modal dialog */
|
|
23
|
+
dialogClassName?: string;
|
|
24
|
+
/** Custom className for the modal content */
|
|
25
|
+
contentClassName?: string;
|
|
26
|
+
/** Custom className for the modal header */
|
|
27
|
+
headerClassName?: string;
|
|
28
|
+
/** Custom className for the modal body */
|
|
29
|
+
bodyClassName?: string;
|
|
30
|
+
/** Custom className for the modal footer */
|
|
31
|
+
footerClassName?: string;
|
|
32
|
+
/** Modal title */
|
|
33
|
+
title?: React.ReactNode;
|
|
34
|
+
/** Modal header content */
|
|
35
|
+
header?: React.ReactNode;
|
|
36
|
+
/** Modal body content */
|
|
37
|
+
children: React.ReactNode;
|
|
38
|
+
/** Modal footer content */
|
|
39
|
+
footer?: React.ReactNode;
|
|
40
|
+
/** Whether to show close button in header */
|
|
41
|
+
closeButton?: boolean;
|
|
42
|
+
}
|
|
43
|
+
declare const Modal: ({ show, onHide, size, centered, backdrop, backdropClose, keyboard, animation, className, dialogClassName, contentClassName, headerClassName, bodyClassName, footerClassName, title, header, children, footer, closeButton }: ModalProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
44
|
+
export default Modal;
|
|
@@ -14,6 +14,8 @@ export interface WhatsAppProps {
|
|
|
14
14
|
tooltipText?: string;
|
|
15
15
|
/** Custom className for the button */
|
|
16
16
|
className?: string;
|
|
17
|
+
/** Custom className for the tooltip */
|
|
18
|
+
tooltipClassName?: string;
|
|
17
19
|
/** Custom styles */
|
|
18
20
|
style?: React.CSSProperties;
|
|
19
21
|
/** Callback when button is clicked */
|
|
@@ -23,5 +25,5 @@ export interface WhatsAppProps {
|
|
|
23
25
|
/** Whether to open in new tab */
|
|
24
26
|
openInNewTab?: boolean;
|
|
25
27
|
}
|
|
26
|
-
declare const WhatsApp: ({ phone, message, position, size, showTooltip, tooltipText, className, style, onClick, zIndex, openInNewTab }: WhatsAppProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
28
|
+
declare const WhatsApp: ({ phone, message, position, size, showTooltip, tooltipText, className, tooltipClassName, style, onClick, zIndex, openInNewTab }: WhatsAppProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
27
29
|
export default WhatsApp;
|
package/package.json
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "luna-components-library",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "A React component library with TypeScript support",
|
|
5
|
-
"main": "dist/luna-components-library.js",
|
|
6
|
-
"module": "dist/luna-components-library.js",
|
|
7
|
-
"types": "dist/src/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"clean": "rimraf dist",
|
|
13
|
-
"build": "npm run clean && vite build",
|
|
14
|
-
"prepublishOnly": "npm run build",
|
|
15
|
-
"test": "jest",
|
|
16
|
-
"dev": "vite --config vite.demo.config.ts",
|
|
17
|
-
"preview": "vite preview --config vite.demo.config.ts",
|
|
18
|
-
"build-demo": "vite build --config vite.demo.config.ts"
|
|
19
|
-
},
|
|
20
|
-
"keywords": [
|
|
21
|
-
"react",
|
|
22
|
-
"components",
|
|
23
|
-
"typescript",
|
|
24
|
-
"ui",
|
|
25
|
-
"library"
|
|
26
|
-
],
|
|
27
|
-
"author": "https://andreychaconresumereact.netlify.app/",
|
|
28
|
-
"license": "MIT",
|
|
29
|
-
"peerDependencies": {
|
|
30
|
-
"react": ">=16.8.0",
|
|
31
|
-
"react-dom": ">=16.8.0"
|
|
32
|
-
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@babel/preset-env": "^7.29.5",
|
|
35
|
-
"@babel/preset-react": "^7.28.5",
|
|
36
|
-
"@babel/preset-typescript": "^7.28.5",
|
|
37
|
-
"@testing-library/jest-dom": "^6.0.0",
|
|
38
|
-
"@testing-library/react": "^16.0.0",
|
|
39
|
-
"@types/jest": "^29.5.0",
|
|
40
|
-
"@types/react": "^19.0.0",
|
|
41
|
-
"@types/react-dom": "^19.0.0",
|
|
42
|
-
"@vitejs/plugin-react": "^6.0.1",
|
|
43
|
-
"babel-jest": "^30.3.0",
|
|
44
|
-
"jest": "^29.0.0",
|
|
45
|
-
"jest-environment-jsdom": "^30.3.0",
|
|
46
|
-
"react": "^19.2.6",
|
|
47
|
-
"react-dom": "^19.2.6",
|
|
48
|
-
"rimraf": "^6.1.3",
|
|
49
|
-
"tslib": "^2.8.1",
|
|
50
|
-
"typescript": "^6.0.3",
|
|
51
|
-
"vite": "^8.0.11",
|
|
52
|
-
"vite-plugin-dts": "^4.0.0"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "luna-components-library",
|
|
3
|
+
"version": "1.1.27",
|
|
4
|
+
"description": "A React component library with TypeScript support",
|
|
5
|
+
"main": "dist/luna-components-library.js",
|
|
6
|
+
"module": "dist/luna-components-library.js",
|
|
7
|
+
"types": "dist/src/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"clean": "rimraf dist",
|
|
13
|
+
"build": "npm run clean && vite build",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"dev": "vite --config vite.demo.config.ts",
|
|
17
|
+
"preview": "vite preview --config vite.demo.config.ts",
|
|
18
|
+
"build-demo": "vite build --config vite.demo.config.ts"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"react",
|
|
22
|
+
"components",
|
|
23
|
+
"typescript",
|
|
24
|
+
"ui",
|
|
25
|
+
"library"
|
|
26
|
+
],
|
|
27
|
+
"author": "https://andreychaconresumereact.netlify.app/",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"react": ">=16.8.0",
|
|
31
|
+
"react-dom": ">=16.8.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@babel/preset-env": "^7.29.5",
|
|
35
|
+
"@babel/preset-react": "^7.28.5",
|
|
36
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
37
|
+
"@testing-library/jest-dom": "^6.0.0",
|
|
38
|
+
"@testing-library/react": "^16.0.0",
|
|
39
|
+
"@types/jest": "^29.5.0",
|
|
40
|
+
"@types/react": "^19.0.0",
|
|
41
|
+
"@types/react-dom": "^19.0.0",
|
|
42
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
43
|
+
"babel-jest": "^30.3.0",
|
|
44
|
+
"jest": "^29.0.0",
|
|
45
|
+
"jest-environment-jsdom": "^30.3.0",
|
|
46
|
+
"react": "^19.2.6",
|
|
47
|
+
"react-dom": "^19.2.6",
|
|
48
|
+
"rimraf": "^6.1.3",
|
|
49
|
+
"tslib": "^2.8.1",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"vite": "^8.0.11",
|
|
52
|
+
"vite-plugin-dts": "^4.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|