luna-components-library 1.1.34 → 1.1.36

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 CHANGED
@@ -54,94 +54,93 @@ import {
54
54
  } from 'luna-components-library';
55
55
 
56
56
  function App() {
57
+ const [showModal, setShowModal] = useState(false);
58
+ const [isLoading, setIsLoading] = useState(false);
59
+
57
60
  return (
58
- <div className="p-4 space-y-4">
59
- <Button
60
- variant="primary"
61
- size="lg"
62
- onClick={() => console.log('Clicked!')}
63
- className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition-colors duration-200"
64
- >
65
- Click me
66
- </Button>
67
-
68
- <Card
69
- title="Example Card"
70
- padding="md"
71
- shadow="lg"
72
- className="max-w-md bg-white border border-gray-200 rounded-lg shadow-lg"
73
- >
74
- <p className="text-gray-700">This is a card component from Luna Components Library.</p>
75
- <Button variant="outline" size="sm" className="mt-2 border border-gray-300 hover:border-gray-400">
76
- Learn More
61
+ <div className="p-4 space-y-6">
62
+ {/* 1. Basic Components */}
63
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
64
+ <Button
65
+ variant="primary"
66
+ onClick={() => setShowModal(true)}
67
+ className="bg-blue-600 hover:bg-blue-700 text-white p-2 rounded"
68
+ >
69
+ Open Modal
77
70
  </Button>
78
- </Card>
71
+
72
+ <Input
73
+ placeholder="Type something..."
74
+ className="border p-2 rounded"
75
+ />
76
+ </div>
79
77
 
80
- <Anchor
81
- href="https://example.com"
82
- variant="secondary"
83
- className="text-gray-600 hover:text-gray-800 underline transition-colors duration-200"
84
- >
85
- Visit Example
86
- </Anchor>
78
+ {/* 2. Content Display */}
79
+ <Card title="Luna Library" className="shadow-md p-4">
80
+ <Typed
81
+ strings={['Modern React Components', 'TypeScript Ready', 'Tailwind Styled']}
82
+ className="text-blue-600 font-bold"
83
+ />
84
+ <p className="mt-2">Building fast and beautiful interfaces.</p>
85
+ </Card>
87
86
 
87
+ {/* 3. Interactive Elements */}
88
88
  <Accordion
89
- key="demo"
90
- active={false}
91
- onClick={() => console.log('Toggle')}
92
- header={<h3 className="font-semibold text-gray-800">Click to expand</h3>}
93
- content={<p className="text-gray-600">This is accordion content!</p>}
94
- className="border border-gray-200 rounded-lg overflow-hidden"
95
- />
96
-
97
- <Spinner
98
- size="md"
99
- type="circle"
100
- className="text-blue-600"
89
+ header="Click to expand"
90
+ content="This is the accordion content!"
91
+ className="border rounded"
101
92
  />
102
93
 
103
- <DropDown
104
- toggle={
105
- <button className="bg-gray-100 hover:bg-gray-200 border border-gray-300 rounded px-3 py-2 text-sm">
106
- Select Option
107
- </button>
108
- }
109
- options={[
110
- { value: 'option1', label: 'Option 1' },
111
- { value: 'option2', label: 'Option 2' },
112
- { value: 'option3', label: 'Option 3' }
113
- ]}
114
- selected="option1"
115
- onChange={(value) => console.log('Selected:', value)}
116
- />
117
-
118
- <Modal
119
- show={true}
120
- onHide={() => console.log('Modal closed')}
121
- title="Modal Title"
122
- className="bg-white rounded-lg shadow-xl"
123
- >
124
- <p className="text-gray-700">This is a modal component from Luna Components Library.</p>
94
+ {/* 4. Feedback & Progress */}
95
+ <div className="space-y-2">
96
+ <p>Loading Progress:</p>
97
+ <ProgressBar progress={75} variant="success" className="h-2 bg-gray-200" />
98
+ <Spinner size="sm" type="dots" className="text-blue-500" />
99
+ </div>
100
+
101
+ {/* 5. Communication & Navigation */}
102
+ <div className="flex gap-4">
103
+ <WhatsApp phone="123456789" message="Hello!" />
104
+ <Anchor href="https://github.com" variant="outline">GitHub Repo</Anchor>
105
+ </div>
106
+
107
+ {/* 6. Overlays (Modals & Preloaders) */}
108
+ <Modal show={showModal} onHide={() => setShowModal(false)} title="Quick Start Modal">
109
+ <p>This is a modal from the library!</p>
125
110
  </Modal>
126
111
 
127
- <ScrollTop
128
- threshold={200}
129
- position="bottom-right"
130
- size="md"
131
- className="bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow-lg"
132
- />
133
-
134
- <Input
135
- inputSize="md"
136
- variant="primary"
137
- placeholder="Enter your text here"
138
- className="border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
139
- />
112
+ {isLoading && <Preloader duration={2000} onComplete={() => setIsLoading(false)} />}
113
+
114
+ <ScrollTop threshold={100} className="bg-blue-600 text-white p-2 rounded-full" />
140
115
  </div>
141
116
  );
142
117
  }
143
118
  ```
144
119
 
120
+ ### ⚓ Hooks & Utilities Quick Start
121
+
122
+ Luna Library also provides powerful hooks and utilities for common tasks:
123
+
124
+ ```javascript
125
+ import { useFetch, useLocalStorage, httpClient, formatters, validators } from 'luna-components-library';
126
+
127
+ // 1. Data Fetching Hook
128
+ const { data, loading, error } = useFetch('https://api.example.com/data');
129
+
130
+ // 2. Direct HTTP Client
131
+ const postData = async () => {
132
+ const result = await httpClient.post('/api/users', { name: 'New User' });
133
+ };
134
+
135
+ // 3. Local Storage Management
136
+ const [theme, setTheme] = useLocalStorage('app-theme', 'light');
137
+
138
+ // 4. Practical Utilities
139
+ const price = formatters.currency(1200.50); // "$1,200.50"
140
+ const isValid = validators.isEmail('user@luna.com'); // true
141
+ ```
142
+
143
+
145
144
  ## 🧩 Components
146
145
 
147
146
  All components use TypeScript with specific types for better type safety and IntelliSense. The library follows a minimal documentation approach with descriptive type names instead of extensive JSDoc comments.
@@ -837,7 +836,7 @@ type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'sea
837
836
  Luna Library now includes generic utilities and hooks to streamline API communication and state management.
838
837
 
839
838
  ### httpClient
840
- A generic HTTP client wrapper for the Fetch API with support for standard HTTP methods. It automatically handles JSON stringification for POST/PUT requests and sets appropriate headers.
839
+ A generic HTTP client wrapper for the Fetch API with support for standard HTTP methods. It automatically handles JSON stringification for POST/PUT requests and sets appropriate headers. Calls apiFetch internally.
841
840
 
842
841
  ```javascript
843
842
  import { httpClient } from 'luna-components-library';
@@ -854,6 +853,21 @@ const response = await httpClient.post('https://api.example.com/posts', {
854
853
  // httpClient.delete(url, options)
855
854
  ```
856
855
 
856
+ ### apiFetch
857
+ A low-level wrapper for the native `fetch` API that includes automatic response parsing and error handling for non-OK HTTP statuses.
858
+
859
+ ```javascript
860
+ import { apiFetch } from 'luna-components-library';
861
+
862
+ try {
863
+ const data = await apiFetch('https://api.example.com/resource');
864
+ console.log(data);
865
+ } catch (error) {
866
+ console.error('Fetch failed:', error.message);
867
+ }
868
+ ```
869
+
870
+
857
871
  ### storage
858
872
  A wrapper for `localStorage` with safety checks and automatic JSON parsing.
859
873
 
@@ -900,7 +914,6 @@ logger.success('User logged in');
900
914
  logger.warn('Low disk space');
901
915
  logger.error('API failed', error);
902
916
  ```
903
- ```
904
917
 
905
918
  ### useFetch
906
919
  A powerful custom hook for performing data fetching. It manages `data`, `error`, and `loading` states automatically and includes built-in `AbortController` support to prevent memory leaks and race conditions.
@@ -926,6 +939,7 @@ function UserList() {
926
939
  </ul>
927
940
  );
928
941
  }
942
+ ```
929
943
 
930
944
  ### useLocalStorage
931
945
  Syncs state with `localStorage` automatically.
@@ -1012,6 +1012,9 @@ var validators = {
1012
1012
  };
1013
1013
  //#endregion
1014
1014
  //#region src/utilities/logger.util.ts
1015
+ /**
1016
+ * Utility for logging messages with different levels.
1017
+ */
1015
1018
  var logStyles = {
1016
1019
  info: "color: #3b82f6; font-weight: bold;",
1017
1020
  warn: "color: #f59e0b; font-weight: bold;",
@@ -1019,12 +1022,18 @@ var logStyles = {
1019
1022
  success: "color: #10b981; font-weight: bold;"
1020
1023
  };
1021
1024
  var logger = {
1022
- info: (message, ...data) => {},
1023
- warn: (message, ...data) => {},
1025
+ info: (message, ...data) => {
1026
+ console.log(`%c[INFO] ${message}`, logStyles.info, ...data);
1027
+ },
1028
+ warn: (message, ...data) => {
1029
+ console.warn(`%c[WARN] ${message}`, logStyles.warn, ...data);
1030
+ },
1024
1031
  error: (message, ...data) => {
1025
1032
  console.error(`%c[ERROR] ${message}`, logStyles.error, ...data);
1026
1033
  },
1027
- success: (message, ...data) => {}
1034
+ success: (message, ...data) => {
1035
+ console.log(`%c[SUCCESS] ${message}`, logStyles.success, ...data);
1036
+ }
1028
1037
  };
1029
1038
  //#endregion
1030
1039
  //#region src/hooks/useFetch.hook.ts
@@ -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","../src/components/Modal.tsx","../src/components/Input.tsx","../src/utilities/apiFetch.util.ts","../src/utilities/httpClient.util.ts","../src/utilities/storage.util.ts","../src/utilities/formatters.util.ts","../src/utilities/validators.util.ts","../src/utilities/logger.util.ts","../src/hooks/useFetch.hook.ts","../src/hooks/useLocalStorage.hook.ts","../src/hooks/useDebounce.hook.ts"],"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\nexport type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | 'link';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type AllButtonProps = React.ComponentPropsWithoutRef<'button'>;\n\nexport type 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 style?: React.CSSProperties;\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 style,\n ...props\n}: AllButtonProps & 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 success: 'bg-green-600 text-white hover:bg-green-700 focus:ring-green-500',\n danger: 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500',\n warning: 'bg-yellow-500 text-white hover:bg-yellow-600 focus:ring-yellow-500',\n info: 'bg-cyan-600 text-white hover:bg-cyan-700 focus:ring-cyan-500',\n dark: 'bg-gray-900 text-white hover:bg-gray-800 focus:ring-gray-900',\n light: 'bg-gray-100 text-gray-900 hover:bg-gray-200 focus:ring-gray-300',\n link: 'text-blue-600 hover:text-blue-800 hover:underline focus:outline-none focus:ring-2 focus:ring-blue-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 style={style}\n {...props}\n >\n {children}\n </button>\n );\n};\n\nexport default Button;\n","import React from 'react';\n\n// Card padding and shadow variants\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg';\nexport type CardShadow = 'none' | 'sm' | 'md' | 'lg';\n\nexport type CardProps = {\n children: React.ReactNode;\n title?: string;\n className?: string;\n containerClassName?: string;\n titleClassName?: string;\n padding?: CardPadding;\n shadow?: CardShadow;\n style?: React.CSSProperties;\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 style,\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} style={style}>\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\nexport type AnchorVariant = 'none' | 'primary' | 'secondary' | 'outline';\r\nexport type AnchorSize = 'sm' | 'md' | 'lg';\r\nexport type AllAnchorProps = React.ComponentPropsWithoutRef<'a'>;\r\n\r\nexport type 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 style?: React.CSSProperties;\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 = variant === 'none' ? 'font-medium transition-colors focus:outline-none' : '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 style,\r\n ...props\r\n}: AnchorProps & AllAnchorProps) => {\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} style={style} {...props}>\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\nexport type 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 style?: React.CSSProperties;\r\n}\r\n\r\nconst Accordion = ({ active,\r\n onClick,\r\n header,\r\n content,\r\n className = '',\r\n containerClassName = 'border border-gray-200 rounded-lg overflow-hidden',\r\n 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',\r\n contentClassName = 'transition-all duration-300 ease-in-out',\r\n style\r\n}: AccordionProps) => {\r\n return (\r\n <div className={`${containerClassName} ${className}`} style={style}>\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\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\nexport type SpinnerType = 'circle' | 'dots' | 'pulse' | 'bars';\n\nexport type SpinnerProps = {\n className?: string;\n containerClassName?: string;\n dotClassName?: string;\n barClassName?: string;\n size?: SpinnerSize;\n type?: SpinnerType;\n style?: React.CSSProperties;\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 style\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 style={style}\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\nexport type 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 style?: React.CSSProperties;\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 style\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}`} style={style}>\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\nexport type ProgressBarVariant = 'primary' | 'success' | 'warning' | 'danger' | 'dark' | 'light';\r\n\r\n// Core progress bar props\r\nexport type 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\nexport type 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 = ({\r\n progress,\r\n max,\r\n min,\r\n 'aria-label': ariaLabel,\r\n className,\r\n style,\r\n containerClassName = 'w-full bg-gray-200 rounded-full h-4 overflow-hidden',\r\n barClassName = 'h-full rounded-full transition-all duration-300 flex items-center justify-center text-xs font-medium',\r\n variant = 'primary'\r\n}: 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} style={style}>\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 }}\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}`} style={style}>\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 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 type 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 /** Custom inline styles */\n style?: React.CSSProperties;\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 style\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, ...style }}\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 type 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 /** Custom inline styles */\n style?: React.CSSProperties;\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 style\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 style={style}\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","import React from 'react';\n\n// Input variants and sizes\nexport type InputVariant = 'none' | 'primary' | 'secondary' | 'outline' | 'danger' | 'success';\nexport type InputSize = 'sm' | 'md' | 'lg' | 'xl';\nexport type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'time' | 'datetime-local' | 'month' | 'week' | 'color' | 'file' | 'hidden' | 'image' | 'range' | 'reset' | 'submit';\n\nexport type AllInputProps = Omit<React.ComponentPropsWithoutRef<'input'>, 'onChange'>;\n\nexport type InputProps = {\n children?: React.ReactNode;\n variant?: InputVariant;\n inputSize?: InputSize;\n type?: InputType;\n placeholder?: string;\n value?: string;\n onChange?: (value: string) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n disabled?: boolean;\n required?: boolean;\n readOnly?: boolean;\n className?: string;\n containerClassName?: string;\n inputClassName?: string;\n variantClassName?: string;\n sizeClassName?: string;\n style?: React.CSSProperties;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n};\n\nconst Input = ({\n children,\n variant = 'none',\n type = 'text',\n inputSize = 'md',\n placeholder,\n value,\n onChange,\n onFocus,\n onBlur,\n disabled = false,\n required = false,\n readOnly = false,\n className = '',\n containerClassName = 'relative inline-block',\n inputClassName = 'border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500',\n variantClassName = '',\n sizeClassName = '',\n style,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: InputProps & AllInputProps) => {\n const baseClasses = containerClassName;\n\n const variantClasses: Record<InputVariant, string> = {\n none: '',\n primary: 'bg-blue-600 text-white border-blue-600 focus:ring-blue-500 focus:border-blue-500',\n secondary: 'bg-gray-600 text-white border-gray-600 focus:ring-gray-500 focus:border-gray-500',\n outline: 'border-gray-300 text-gray-700 bg-white focus:ring-blue-500 focus:border-blue-500',\n danger: 'bg-red-600 text-white border-red-600 focus:ring-red-500 focus:border-red-500',\n success: 'bg-green-600 text-white border-green-600 focus:ring-green-500 focus:border-green-500'\n };\n\n const sizeClasses: Record<InputSize, string> = {\n sm: 'px-2 py-1 text-sm',\n md: 'px-3 py-2 text-base',\n lg: 'px-4 py-3 text-lg',\n xl: 'px-6 py-4 text-xl'\n };\n\n const classes = `\n ${baseClasses}\n ${variantClasses[variant]}\n ${sizeClasses[inputSize]}\n ${variantClassName}\n ${sizeClassName}\n ${className}\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${readOnly ? 'bg-gray-100 cursor-not-allowed' : ''}\n `.trim();\n\n return (\n <div className={classes} style={style}>\n {children && (\n <label\n htmlFor={id}\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n {children}\n </label>\n )}\n <input\n id={id}\n type={type}\n placeholder={placeholder}\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n onFocus={onFocus}\n onBlur={onBlur}\n disabled={disabled}\n required={required}\n readOnly={readOnly}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n className={`\n ${inputClassName}\n ${variantClasses[variant]}\n ${sizeClasses[inputSize]}\n ${variantClassName}\n ${sizeClassName}\n `.trim()}\n {...props}\n />\n </div>\n );\n};\n\nexport default Input;\n","/**\n * A generic wrapper for the fetch API with error handling and response parsing.\n * @param url - The URL to fetch\n * @param options - Fetch options (method, headers, body, signal, etc.)\n * @returns Parsed JSON response\n */\nexport const apiFetch = async (url: string, options?: RequestInit) => {\n try {\n const response = await fetch(url, options);\n\n if (!response.ok) {\n // Handles 4xx and 5xx errors\n throw new Error(`HTTP error! Status: ${response.status} - ${response.statusText}`);\n }\n\n // Return the parsed JSON data\n return await response.json();\n } catch (error) {\n // Handle fetch cancellation\n if (error instanceof DOMException && error.name === 'AbortError') {\n console.log('Fetch aborted');\n return;\n }\n \n // Handle other errors\n if (error instanceof Error) {\n throw new Error(error.message);\n }\n \n throw new Error(String(error));\n }\n};\n","import { apiFetch } from \"./apiFetch.util\";\n\n/**\n * Generic GET request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param options - Additional fetch options\n */\nexport const get = async <T>(url: string, options?: RequestInit): Promise<T> => {\n return apiFetch(url, { ...options, method: 'GET' });\n};\n\n/**\n * Generic POST request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param body - Data to send\n * @param options - Additional fetch options\n */\nexport const post = async <T>(url: string, body: any, options?: RequestInit): Promise<T> => {\n return apiFetch(url, {\n ...options,\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n });\n};\n\n/**\n * Generic PUT request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param body - Data to send\n * @param options - Additional fetch options\n */\nexport const put = async <T>(url: string, body: any, options?: RequestInit): Promise<T> => {\n return apiFetch(url, {\n ...options,\n method: 'PUT',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n });\n};\n\n/**\n * Generic DELETE request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param options - Additional fetch options\n */\nexport const del = async <T>(url: string, options?: RequestInit): Promise<T> => {\n return apiFetch(url, { ...options, method: 'DELETE' });\n};\n\n// Generic HTTP Client Object\nexport const httpClient = {\n get,\n post,\n put,\n delete: del,\n};\n","/**\n * Utility for interacting with localStorage safely.\n */\nexport const storage = {\n get: <T>(key: string, defaultValue: T): T => {\n try {\n const item = window.localStorage.getItem(key);\n return item ? JSON.parse(item) : defaultValue;\n } catch (error) {\n console.error(`Error reading key \"${key}\" from storage:`, error);\n return defaultValue;\n }\n },\n\n set: <T>(key: string, value: T): void => {\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch (error) {\n console.error(`Error writing key \"${key}\" to storage:`, error);\n }\n },\n\n remove: (key: string): void => {\n try {\n window.localStorage.removeItem(key);\n } catch (error) {\n console.error(`Error removing key \"${key}\" from storage:`, error);\n }\n },\n\n clear: (): void => {\n try {\n window.localStorage.clear();\n } catch (error) {\n console.error('Error clearing storage:', error);\n }\n }\n};\n","/**\n * Utility functions for formatting data.\n */\nexport const formatters = {\n /**\n * Formats a number as currency.\n * @param value - Number to format\n * @param locale - Locale (default: 'en-US')\n * @param currency - Currency code (default: 'USD')\n */\n currency: (value: number, locale: string = 'en-US', currency: string = 'USD'): string => {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currency,\n }).format(value);\n },\n\n /**\n * Formats a date to a readable string.\n * @param date - Date to format\n * @param locale - Locale (default: 'en-US')\n * @param options - Intl.DateTimeFormatOptions\n */\n date: (date: Date | string | number, locale: string = 'en-US', options?: Intl.DateTimeFormatOptions): string => {\n const d = new Date(date);\n const defaultOptions: Intl.DateTimeFormatOptions = options || {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n };\n return new Intl.DateTimeFormat(locale, defaultOptions).format(d);\n },\n\n /**\n * Truncates a string to a specific length.\n */\n truncate: (str: string, length: number): string => {\n if (str.length <= length) return str;\n return str.slice(0, length) + '...';\n }\n};\n","/**\n * Utility functions for common validations.\n */\nexport const validators = {\n /**\n * Checks if a string is a valid email.\n */\n isEmail: (email: string): boolean => {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(email);\n },\n\n /**\n * Checks if a string is empty or only whitespace.\n */\n isEmpty: (str: string | null | undefined): boolean => {\n return !str || str.trim().length === 0;\n },\n\n /**\n * Checks if a value is a number.\n */\n isNumber: (value: any): boolean => {\n return !isNaN(parseFloat(value)) && isFinite(value);\n },\n\n /**\n * Validates if a password meets minimum complexity.\n * (At least 8 chars, 1 letter, 1 number)\n */\n isStrongPassword: (password: string): boolean => {\n return password.length >= 8 && /[A-Za-z]/.test(password) && /[0-9]/.test(password);\n },\n\n /**\n * Validates a phone number.\n * @param phone - Phone number string\n * @param locale - Optional locale (default: 'generic')\n */\n isPhone: (phone: string, locale: string = 'generic'): boolean => {\n const cleanPhone = phone.replace(/\\s|-/g, '');\n if (locale === 'es-CR') {\n // Costa Rica: 8 digits, starts with 2, 4, 5, 6, 7 or 8\n return /^[245678]\\d{7}$/.test(cleanPhone);\n }\n // Generic: at least 7 digits\n return /^\\+?[\\d\\s-]{7,}$/.test(cleanPhone);\n }\n};\n","/**\n * Utility for logging messages with different levels and optional environment check.\n */\nconst isDev = process.env.NODE_ENV === 'development';\n\nconst logStyles = {\n info: 'color: #3b82f6; font-weight: bold;',\n warn: 'color: #f59e0b; font-weight: bold;',\n error: 'color: #ef4444; font-weight: bold;',\n success: 'color: #10b981; font-weight: bold;'\n};\n\nexport const logger = {\n info: (message: string, ...data: any[]): void => {\n if (isDev) {\n console.log(`%c[INFO] ${message}`, logStyles.info, ...data);\n }\n },\n\n warn: (message: string, ...data: any[]): void => {\n if (isDev) {\n console.warn(`%c[WARN] ${message}`, logStyles.warn, ...data);\n }\n },\n\n error: (message: string, ...data: any[]): void => {\n // Errors are usually logged even in production for debugging\n console.error(`%c[ERROR] ${message}`, logStyles.error, ...data);\n },\n\n success: (message: string, ...data: any[]): void => {\n if (isDev) {\n console.log(`%c[SUCCESS] ${message}`, logStyles.success, ...data);\n }\n }\n};\n","import { useState, useEffect } from 'react';\nimport { apiFetch } from '../utilities/apiFetch.util';\n\ntype Data<T> = T | null;\ntype ErrorType = Error | null | string | null;\n\ntype Params<T> = {\n data: Data<T>;\n error: ErrorType;\n loading: boolean;\n};\n\n/**\n * Custom hook to perform a fetch request and manage its state (data, error, loading).\n * @template T - Expected return type\n * @param url - URL to fetch\n * @param options - Optional configuration (e.g., delay for testing)\n * @returns Object with data, error, and loading state\n */\nexport const useFetch = <T>(url: string, options?: { delay?: number }): Params<T> => {\n const [data, setData] = useState<Data<T>>(null);\n const [error, setError] = useState<ErrorType>(null);\n const [loading, setLoading] = useState<boolean>(true);\n\n useEffect(() => {\n const controller = new AbortController();\n const { signal } = controller;\n\n const fetchData = async () => {\n setLoading(true);\n \n if (options?.delay) {\n await new Promise(resolve => setTimeout(resolve, options.delay));\n }\n\n try {\n const result: T = await apiFetch(url, { signal });\n setData(result);\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n console.log('Fetch aborted');\n } else if (err instanceof Error) {\n setError(err.message);\n } else {\n setError(String(err));\n }\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n\n return () => {\n controller.abort();\n };\n }, [url]);\n\n return { data, error, loading };\n};\n","import { useState, useEffect } from 'react';\n\n/**\n * Custom hook to manage localStorage with React state.\n * @param key - The key to store in localStorage\n * @param initialValue - Initial value if none exists\n * @returns [storedValue, setValue] - State and setter function\n */\nexport function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void] {\n // State to store our value\n // Pass initial state function to useState so logic is only executed once\n const [storedValue, setStoredValue] = useState<T>(() => {\n if (typeof window === 'undefined') {\n return initialValue;\n }\n try {\n const item = window.localStorage.getItem(key);\n return item ? JSON.parse(item) : initialValue;\n } catch (error) {\n console.error(`Error reading localStorage key \"${key}\":`, error);\n return initialValue;\n }\n });\n\n // Return a wrapped version of useState's setter function that\n // persists the new value to localStorage.\n const setValue = (value: T | ((val: T) => T)) => {\n try {\n // Allow value to be a function so we have same API as useState\n const valueToStore = value instanceof Function ? value(storedValue) : value;\n setStoredValue(valueToStore);\n if (typeof window !== 'undefined') {\n window.localStorage.setItem(key, JSON.stringify(valueToStore));\n }\n } catch (error) {\n console.error(`Error setting localStorage key \"${key}\":`, error);\n }\n };\n\n return [storedValue, setValue];\n}\n","import { useState, useEffect } from 'react';\n\n/**\n * Custom hook to debounce a value.\n * @param value - The value to debounce\n * @param delay - Delay in milliseconds (default 500)\n * @returns The debounced value\n */\nexport function useDebounce<T>(value: T, delay: number = 500): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n // Update debounced value after delay\n const handler = setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n // Cancel the timeout if value changes (or on unmount)\n return () => {\n clearTimeout(handler);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\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","../src/components/Input.tsx","../src/utilities/apiFetch.util.ts","../src/utilities/httpClient.util.ts","../src/utilities/storage.util.ts","../src/utilities/formatters.util.ts","../src/utilities/validators.util.ts","../src/utilities/logger.util.ts","../src/hooks/useFetch.hook.ts","../src/hooks/useLocalStorage.hook.ts","../src/hooks/useDebounce.hook.ts"],"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\nexport type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | 'link';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type AllButtonProps = React.ComponentPropsWithoutRef<'button'>;\n\nexport type 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 style?: React.CSSProperties;\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 style,\n ...props\n}: AllButtonProps & 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 success: 'bg-green-600 text-white hover:bg-green-700 focus:ring-green-500',\n danger: 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500',\n warning: 'bg-yellow-500 text-white hover:bg-yellow-600 focus:ring-yellow-500',\n info: 'bg-cyan-600 text-white hover:bg-cyan-700 focus:ring-cyan-500',\n dark: 'bg-gray-900 text-white hover:bg-gray-800 focus:ring-gray-900',\n light: 'bg-gray-100 text-gray-900 hover:bg-gray-200 focus:ring-gray-300',\n link: 'text-blue-600 hover:text-blue-800 hover:underline focus:outline-none focus:ring-2 focus:ring-blue-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 style={style}\n {...props}\n >\n {children}\n </button>\n );\n};\n\nexport default Button;\n","import React from 'react';\n\n// Card padding and shadow variants\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg';\nexport type CardShadow = 'none' | 'sm' | 'md' | 'lg';\n\nexport type CardProps = {\n children: React.ReactNode;\n title?: string;\n className?: string;\n containerClassName?: string;\n titleClassName?: string;\n padding?: CardPadding;\n shadow?: CardShadow;\n style?: React.CSSProperties;\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 style,\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} style={style}>\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\nexport type AnchorVariant = 'none' | 'primary' | 'secondary' | 'outline';\r\nexport type AnchorSize = 'sm' | 'md' | 'lg';\r\nexport type AllAnchorProps = React.ComponentPropsWithoutRef<'a'>;\r\n\r\nexport type 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 style?: React.CSSProperties;\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 = variant === 'none' ? 'font-medium transition-colors focus:outline-none' : '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 style,\r\n ...props\r\n}: AnchorProps & AllAnchorProps) => {\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} style={style} {...props}>\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\nexport type 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 style?: React.CSSProperties;\r\n}\r\n\r\nconst Accordion = ({ active,\r\n onClick,\r\n header,\r\n content,\r\n className = '',\r\n containerClassName = 'border border-gray-200 rounded-lg overflow-hidden',\r\n 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',\r\n contentClassName = 'transition-all duration-300 ease-in-out',\r\n style\r\n}: AccordionProps) => {\r\n return (\r\n <div className={`${containerClassName} ${className}`} style={style}>\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\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\nexport type SpinnerType = 'circle' | 'dots' | 'pulse' | 'bars';\n\nexport type SpinnerProps = {\n className?: string;\n containerClassName?: string;\n dotClassName?: string;\n barClassName?: string;\n size?: SpinnerSize;\n type?: SpinnerType;\n style?: React.CSSProperties;\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 style\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 style={style}\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\nexport type 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 style?: React.CSSProperties;\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 style\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}`} style={style}>\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\nexport type ProgressBarVariant = 'primary' | 'success' | 'warning' | 'danger' | 'dark' | 'light';\r\n\r\n// Core progress bar props\r\nexport type 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\nexport type 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 = ({\r\n progress,\r\n max,\r\n min,\r\n 'aria-label': ariaLabel,\r\n className,\r\n style,\r\n containerClassName = 'w-full bg-gray-200 rounded-full h-4 overflow-hidden',\r\n barClassName = 'h-full rounded-full transition-all duration-300 flex items-center justify-center text-xs font-medium',\r\n variant = 'primary'\r\n}: 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} style={style}>\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 }}\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}`} style={style}>\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 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 type 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 /** Custom inline styles */\n style?: React.CSSProperties;\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 style\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, ...style }}\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 type 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 /** Custom inline styles */\n style?: React.CSSProperties;\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 style\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 style={style}\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","import React from 'react';\n\n// Input variants and sizes\nexport type InputVariant = 'none' | 'primary' | 'secondary' | 'outline' | 'danger' | 'success';\nexport type InputSize = 'sm' | 'md' | 'lg' | 'xl';\nexport type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'time' | 'datetime-local' | 'month' | 'week' | 'color' | 'file' | 'hidden' | 'image' | 'range' | 'reset' | 'submit';\n\nexport type AllInputProps = Omit<React.ComponentPropsWithoutRef<'input'>, 'onChange'>;\n\nexport type InputProps = {\n children?: React.ReactNode;\n variant?: InputVariant;\n inputSize?: InputSize;\n type?: InputType;\n placeholder?: string;\n value?: string;\n onChange?: (value: string) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n disabled?: boolean;\n required?: boolean;\n readOnly?: boolean;\n className?: string;\n containerClassName?: string;\n inputClassName?: string;\n variantClassName?: string;\n sizeClassName?: string;\n style?: React.CSSProperties;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n};\n\nconst Input = ({\n children,\n variant = 'none',\n type = 'text',\n inputSize = 'md',\n placeholder,\n value,\n onChange,\n onFocus,\n onBlur,\n disabled = false,\n required = false,\n readOnly = false,\n className = '',\n containerClassName = 'relative inline-block',\n inputClassName = 'border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500',\n variantClassName = '',\n sizeClassName = '',\n style,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: InputProps & AllInputProps) => {\n const baseClasses = containerClassName;\n\n const variantClasses: Record<InputVariant, string> = {\n none: '',\n primary: 'bg-blue-600 text-white border-blue-600 focus:ring-blue-500 focus:border-blue-500',\n secondary: 'bg-gray-600 text-white border-gray-600 focus:ring-gray-500 focus:border-gray-500',\n outline: 'border-gray-300 text-gray-700 bg-white focus:ring-blue-500 focus:border-blue-500',\n danger: 'bg-red-600 text-white border-red-600 focus:ring-red-500 focus:border-red-500',\n success: 'bg-green-600 text-white border-green-600 focus:ring-green-500 focus:border-green-500'\n };\n\n const sizeClasses: Record<InputSize, string> = {\n sm: 'px-2 py-1 text-sm',\n md: 'px-3 py-2 text-base',\n lg: 'px-4 py-3 text-lg',\n xl: 'px-6 py-4 text-xl'\n };\n\n const classes = `\n ${baseClasses}\n ${variantClasses[variant]}\n ${sizeClasses[inputSize]}\n ${variantClassName}\n ${sizeClassName}\n ${className}\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${readOnly ? 'bg-gray-100 cursor-not-allowed' : ''}\n `.trim();\n\n return (\n <div className={classes} style={style}>\n {children && (\n <label\n htmlFor={id}\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n {children}\n </label>\n )}\n <input\n id={id}\n type={type}\n placeholder={placeholder}\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n onFocus={onFocus}\n onBlur={onBlur}\n disabled={disabled}\n required={required}\n readOnly={readOnly}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n className={`\n ${inputClassName}\n ${variantClasses[variant]}\n ${sizeClasses[inputSize]}\n ${variantClassName}\n ${sizeClassName}\n `.trim()}\n {...props}\n />\n </div>\n );\n};\n\nexport default Input;\n","/**\n * A generic wrapper for the fetch API with error handling and response parsing.\n * @param url - The URL to fetch\n * @param options - Fetch options (method, headers, body, signal, etc.)\n * @returns Parsed JSON response\n */\nexport const apiFetch = async (url: string, options?: RequestInit) => {\n try {\n const response = await fetch(url, options);\n\n if (!response.ok) {\n // Handles 4xx and 5xx errors\n throw new Error(`HTTP error! Status: ${response.status} - ${response.statusText}`);\n }\n\n // Return the parsed JSON data\n return await response.json();\n } catch (error) {\n // Handle fetch cancellation\n if (error instanceof DOMException && error.name === 'AbortError') {\n console.log('Fetch aborted');\n return;\n }\n \n // Handle other errors\n if (error instanceof Error) {\n throw new Error(error.message);\n }\n \n throw new Error(String(error));\n }\n};\n","import { apiFetch } from \"./apiFetch.util\";\n\n/**\n * Generic GET request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param options - Additional fetch options\n */\nexport const get = async <T>(url: string, options?: RequestInit): Promise<T> => {\n return apiFetch(url, { ...options, method: 'GET' });\n};\n\n/**\n * Generic POST request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param body - Data to send\n * @param options - Additional fetch options\n */\nexport const post = async <T>(url: string, body: any, options?: RequestInit): Promise<T> => {\n return apiFetch(url, {\n ...options,\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n });\n};\n\n/**\n * Generic PUT request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param body - Data to send\n * @param options - Additional fetch options\n */\nexport const put = async <T>(url: string, body: any, options?: RequestInit): Promise<T> => {\n return apiFetch(url, {\n ...options,\n method: 'PUT',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n });\n};\n\n/**\n * Generic DELETE request\n * @template T - Expected return type\n * @param url - Full URL or endpoint\n * @param options - Additional fetch options\n */\nexport const del = async <T>(url: string, options?: RequestInit): Promise<T> => {\n return apiFetch(url, { ...options, method: 'DELETE' });\n};\n\n// Generic HTTP Client Object\nexport const httpClient = {\n get,\n post,\n put,\n delete: del,\n};\n","/**\n * Utility for interacting with localStorage safely.\n */\nexport const storage = {\n get: <T>(key: string, defaultValue: T): T => {\n try {\n const item = window.localStorage.getItem(key);\n return item ? JSON.parse(item) : defaultValue;\n } catch (error) {\n console.error(`Error reading key \"${key}\" from storage:`, error);\n return defaultValue;\n }\n },\n\n set: <T>(key: string, value: T): void => {\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch (error) {\n console.error(`Error writing key \"${key}\" to storage:`, error);\n }\n },\n\n remove: (key: string): void => {\n try {\n window.localStorage.removeItem(key);\n } catch (error) {\n console.error(`Error removing key \"${key}\" from storage:`, error);\n }\n },\n\n clear: (): void => {\n try {\n window.localStorage.clear();\n } catch (error) {\n console.error('Error clearing storage:', error);\n }\n }\n};\n","/**\n * Utility functions for formatting data.\n */\nexport const formatters = {\n /**\n * Formats a number as currency.\n * @param value - Number to format\n * @param locale - Locale (default: 'en-US')\n * @param currency - Currency code (default: 'USD')\n */\n currency: (value: number, locale: string = 'en-US', currency: string = 'USD'): string => {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currency,\n }).format(value);\n },\n\n /**\n * Formats a date to a readable string.\n * @param date - Date to format\n * @param locale - Locale (default: 'en-US')\n * @param options - Intl.DateTimeFormatOptions\n */\n date: (date: Date | string | number, locale: string = 'en-US', options?: Intl.DateTimeFormatOptions): string => {\n const d = new Date(date);\n const defaultOptions: Intl.DateTimeFormatOptions = options || {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n };\n return new Intl.DateTimeFormat(locale, defaultOptions).format(d);\n },\n\n /**\n * Truncates a string to a specific length.\n */\n truncate: (str: string, length: number): string => {\n if (str.length <= length) return str;\n return str.slice(0, length) + '...';\n }\n};\n","/**\n * Utility functions for common validations.\n */\nexport const validators = {\n /**\n * Checks if a string is a valid email.\n */\n isEmail: (email: string): boolean => {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(email);\n },\n\n /**\n * Checks if a string is empty or only whitespace.\n */\n isEmpty: (str: string | null | undefined): boolean => {\n return !str || str.trim().length === 0;\n },\n\n /**\n * Checks if a value is a number.\n */\n isNumber: (value: any): boolean => {\n return !isNaN(parseFloat(value)) && isFinite(value);\n },\n\n /**\n * Validates if a password meets minimum complexity.\n * (At least 8 chars, 1 letter, 1 number)\n */\n isStrongPassword: (password: string): boolean => {\n return password.length >= 8 && /[A-Za-z]/.test(password) && /[0-9]/.test(password);\n },\n\n /**\n * Validates a phone number.\n * @param phone - Phone number string\n * @param locale - Optional locale (default: 'generic')\n */\n isPhone: (phone: string, locale: string = 'generic'): boolean => {\n const cleanPhone = phone.replace(/\\s|-/g, '');\n if (locale === 'es-CR') {\n // Costa Rica: 8 digits, starts with 2, 4, 5, 6, 7 or 8\n return /^[245678]\\d{7}$/.test(cleanPhone);\n }\n // Generic: at least 7 digits\n return /^\\+?[\\d\\s-]{7,}$/.test(cleanPhone);\n }\n};\n","/**\n * Utility for logging messages with different levels.\n */\n\nconst logStyles = {\n info: 'color: #3b82f6; font-weight: bold;',\n warn: 'color: #f59e0b; font-weight: bold;',\n error: 'color: #ef4444; font-weight: bold;',\n success: 'color: #10b981; font-weight: bold;'\n};\n\nexport const logger = {\n info: (message: string, ...data: any[]): void => {\n console.log(`%c[INFO] ${message}`, logStyles.info, ...data);\n },\n\n warn: (message: string, ...data: any[]): void => {\n console.warn(`%c[WARN] ${message}`, logStyles.warn, ...data);\n },\n\n error: (message: string, ...data: any[]): void => {\n console.error(`%c[ERROR] ${message}`, logStyles.error, ...data);\n },\n\n success: (message: string, ...data: any[]): void => {\n console.log(`%c[SUCCESS] ${message}`, logStyles.success, ...data);\n }\n};\n","import { useState, useEffect } from 'react';\nimport { apiFetch } from '../utilities/apiFetch.util';\n\ntype Data<T> = T | null;\ntype ErrorType = Error | null | string | null;\n\ntype Params<T> = {\n data: Data<T>;\n error: ErrorType;\n loading: boolean;\n};\n\n/**\n * Custom hook to perform a fetch request and manage its state (data, error, loading).\n * @template T - Expected return type\n * @param url - URL to fetch\n * @param options - Optional configuration (e.g., delay for testing)\n * @returns Object with data, error, and loading state\n */\nexport const useFetch = <T>(url: string, options?: { delay?: number }): Params<T> => {\n const [data, setData] = useState<Data<T>>(null);\n const [error, setError] = useState<ErrorType>(null);\n const [loading, setLoading] = useState<boolean>(true);\n\n useEffect(() => {\n const controller = new AbortController();\n const { signal } = controller;\n\n const fetchData = async () => {\n setLoading(true);\n \n if (options?.delay) {\n await new Promise(resolve => setTimeout(resolve, options.delay));\n }\n\n try {\n const result: T = await apiFetch(url, { signal });\n setData(result);\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n console.log('Fetch aborted');\n } else if (err instanceof Error) {\n setError(err.message);\n } else {\n setError(String(err));\n }\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n\n return () => {\n controller.abort();\n };\n }, [url]);\n\n return { data, error, loading };\n};\n","import { useState, useEffect } from 'react';\n\n/**\n * Custom hook to manage localStorage with React state.\n * @param key - The key to store in localStorage\n * @param initialValue - Initial value if none exists\n * @returns [storedValue, setValue] - State and setter function\n */\nexport function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void] {\n // State to store our value\n // Pass initial state function to useState so logic is only executed once\n const [storedValue, setStoredValue] = useState<T>(() => {\n if (typeof window === 'undefined') {\n return initialValue;\n }\n try {\n const item = window.localStorage.getItem(key);\n return item ? JSON.parse(item) : initialValue;\n } catch (error) {\n console.error(`Error reading localStorage key \"${key}\":`, error);\n return initialValue;\n }\n });\n\n // Return a wrapped version of useState's setter function that\n // persists the new value to localStorage.\n const setValue = (value: T | ((val: T) => T)) => {\n try {\n // Allow value to be a function so we have same API as useState\n const valueToStore = value instanceof Function ? value(storedValue) : value;\n setStoredValue(valueToStore);\n if (typeof window !== 'undefined') {\n window.localStorage.setItem(key, JSON.stringify(valueToStore));\n }\n } catch (error) {\n console.error(`Error setting localStorage key \"${key}\":`, error);\n }\n };\n\n return [storedValue, setValue];\n}\n","import { useState, useEffect } from 'react';\n\n/**\n * Custom hook to debounce a value.\n * @param value - The value to debounce\n * @param delay - Delay in milliseconds (default 500)\n * @returns The debounced value\n */\nexport function useDebounce<T>(value: T, delay: number = 500): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n // Update debounced value after delay\n const handler = setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n // Cancel the timeout if value changes (or on unmount)\n return () => {\n clearTimeout(handler);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Utility for logging messages with different levels.
3
+ */
1
4
  export declare const logger: {
2
5
  info: (message: string, ...data: any[]) => void;
3
6
  warn: (message: string, ...data: any[]) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luna-components-library",
3
- "version": "1.1.34",
3
+ "version": "1.1.36",
4
4
  "description": "A React component library with TypeScript support",
5
5
  "main": "dist/luna-components-library.js",
6
6
  "module": "dist/luna-components-library.js",