luna-components-library 1.1.34 → 1.1.37

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
@@ -7,10 +7,12 @@ A modern React component library built with TypeScript and Vite, designed for re
7
7
  - 🚀 **Built with Vite** - Fast development and optimized builds
8
8
  - 📝 **TypeScript Support** - Full type safety and IntelliSense
9
9
  - 🎨 **Modern Components** - Clean, accessible, and customizable UI components
10
- - 🎯 **Tailwind CSS Styled** - Components use Tailwind CSS utility classes for styling
10
+ - 🎯 **Zero Dependencies** - Components use a pure inline-style architecture for maximum portability
11
11
  - 📦 **Tree-shakable** - Only bundle what you use
12
12
  - 🔧 **Multiple Formats** - ES modules and UMD bundles
13
13
  - 📚 **Type Declarations** - Complete TypeScript definitions included
14
+ - 🧩 **Centralized Design System** - All design tokens, variants, and shared styles live in `src/styles.ts` for consistency
15
+ - 🎭 **className Passthrough** - Every component accepts a `className` prop applied to the outermost element
14
16
 
15
17
  ## 📦 Installation
16
18
 
@@ -22,126 +24,102 @@ yarn add luna-components-library
22
24
  pnpm add luna-components-library
23
25
  ```
24
26
 
25
- **⚠️ Important:** This library uses **Tailwind CSS** for styling. Make sure you have Tailwind CSS configured in your project:
26
-
27
- ```bash
28
- npm install tailwindcss
29
- npx tailwindcss init -p
30
- ```
31
-
32
- Then add the library's components to your `tailwind.config.js`:
33
-
34
- ```js
35
- module.exports = {
36
- content: [
37
- "./src/**/*.{js,jsx,ts,tsx}",
38
- "./node_modules/luna-components-library/dist/**/*.{js,ts,jsx,tsx}"
39
- ],
40
- // ... rest of your config
41
- }
42
- ```
43
-
44
- **💡 Tailwind CSS Best Practices with Luna Library:**
45
- To ensure Tailwind CSS successfully generates and includes the necessary utility classes in your target project's build, it is highly recommended to explicitly provide all necessary styling and positioning classes via the `className` prop for each component you use. By manually specifying these classes (e.g., `className="bg-blue-600 text-white p-4"`), you guarantee that Tailwind's scanner in your main project detects them and includes them in your final CSS file without relying exclusively on the node_modules parser.
27
+ **💡 No Setup Required:**
28
+ Luna Library is fully standalone. All styles are encapsulated within the components using inline styles and dynamic CSS injection, meaning you do not need to install Tailwind CSS, PostCSS, Bootstrap, or any other styling framework to use it. Just install and import!
46
29
 
47
30
  ## 🚀 Quick Start
48
31
 
49
32
  ```jsx
33
+ import { useState } from 'react';
50
34
  import {
51
- Button, Card, Anchor, Accordion, Spinner, DropDown,
52
- ProgressBar, Preloader, ScrollTop, Modal, Input,
53
- WhatsApp, Typed
35
+ Button, Input, Card, Typed, Accordion, ProgressBar, Spinner,
36
+ Preloader, ScrollTop, Modal, WhatsApp, DataTable
54
37
  } from 'luna-components-library';
55
38
 
56
39
  function App() {
40
+ const [showModal, setShowModal] = useState(false);
41
+
57
42
  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
43
+ <div style={{ padding: '2rem', display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
44
+ {/* 1. Basic Components */}
45
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }}>
46
+ <Button
47
+ variant="primary"
48
+ onClick={() => setShowModal(true)}
49
+ >
50
+ Open Modal
77
51
  </Button>
78
- </Card>
52
+
53
+ <Input
54
+ placeholder="Type something..."
55
+ />
56
+ </div>
79
57
 
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>
58
+ {/* 2. Content Display */}
59
+ <Card title="Luna Library" padding="md" shadow="sm">
60
+ <Typed
61
+ strings={['Modern React Components', 'TypeScript Ready', 'Zero Dependencies']}
62
+ />
63
+ <p style={{ marginTop: '0.5rem' }}>Building fast and beautiful interfaces.</p>
64
+ </Card>
87
65
 
66
+ {/* 3. Interactive Elements */}
88
67
  <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"
101
- />
102
-
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"
68
+ title="Click to expand"
123
69
  >
124
- <p className="text-gray-700">This is a modal component from Luna Components Library.</p>
70
+ <p>This is the accordion content!</p>
71
+ </Accordion>
72
+
73
+ {/* 4. Feedback & Progress */}
74
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
75
+ <p>Loading Progress:</p>
76
+ <ProgressBar progress={75} />
77
+ <Spinner size="sm" type="dots" />
78
+ </div>
79
+
80
+ {/* 5. Communication & Navigation */}
81
+ <div style={{ display: 'flex', gap: '1rem' }}>
82
+ <WhatsApp phone="123456789" message="Hello!" />
83
+ <Anchor href="https://github.com" variant="outline">GitHub Repo</Anchor>
84
+ </div>
85
+
86
+ {/* 6. Overlays (Modals & Preloaders) */}
87
+ <Modal isOpen={showModal} onClose={() => setShowModal(false)} title="Quick Start Modal">
88
+ <p>This is a modal from the library!</p>
125
89
  </Modal>
126
90
 
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
- />
91
+ <Preloader isLoading={isLoading} duration={2000} onComplete={() => setIsLoading(false)} />
92
+
93
+ <ScrollTop />
140
94
  </div>
141
95
  );
142
96
  }
143
97
  ```
144
98
 
99
+ ### ⚓ Hooks & Utilities Quick Start
100
+
101
+ Luna Library also provides powerful hooks and utilities for common tasks:
102
+
103
+ ```javascript
104
+ import { useFetch, useLocalStorage, httpClient, formatters, validators } from 'luna-components-library';
105
+
106
+ // 1. Data Fetching Hook
107
+ const { data, loading, error } = useFetch('https://api.example.com/data');
108
+
109
+ // 2. Direct HTTP Client
110
+ const postData = async () => {
111
+ const result = await httpClient.post('/api/users', { name: 'New User' });
112
+ };
113
+
114
+ // 3. Local Storage Management
115
+ const [theme, setTheme] = useLocalStorage('app-theme', 'light');
116
+
117
+ // 4. Practical Utilities
118
+ const price = formatters.currency(1200.50); // "$1,200.50"
119
+ const isValid = validators.isEmail('user@luna.com'); // true
120
+ ```
121
+
122
+
145
123
  ## 🧩 Components
146
124
 
147
125
  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.
@@ -155,7 +133,6 @@ A versatile button component with multiple variants and sizes.
155
133
  size="md"
156
134
  onClick={handleClick}
157
135
  disabled={false}
158
- className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition-colors duration-200"
159
136
  >
160
137
  Button Text
161
138
  </Button>
@@ -165,7 +142,7 @@ A versatile button component with multiple variants and sizes.
165
142
  - `children`: React.ReactNode - Button content
166
143
  - `variant?: ButtonVariant` - Button style (default: 'primary')
167
144
  - `size?: ButtonSize` - Button size (default: 'md')
168
- - `onClick?: () => void` - Click handler
145
+ - `onClick?: React.MouseEventHandler<HTMLButtonElement>` - Click handler
169
146
  - `disabled?: boolean` - Disable button (default: false)
170
147
  - `className?: string` - Additional CSS classes
171
148
  - `style?: React.CSSProperties` - Custom inline styles
@@ -248,35 +225,32 @@ type AnchorSize = 'sm' | 'md' | 'lg';
248
225
  ```
249
226
 
250
227
  ### Accordion
251
- A collapsible content component with customizable header and content sections.
228
+ A collapsible content component with customizable header and animation.
252
229
 
253
230
  ```jsx
254
231
  <Accordion
255
- key="accordion-1"
256
- active={isActive}
257
- onClick={() => setIsActive(!isActive)}
258
- header={<h3 className="font-semibold text-gray-800">Accordion Title</h3>}
259
- content={<p className="text-gray-600">Accordion content goes here</p>}
260
- className="border border-gray-200 rounded-lg overflow-hidden"
261
- containerClassName="border border-gray-200 rounded-lg overflow-hidden"
262
- 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"
263
- contentClassName="transition-all duration-300 ease-in-out"
264
- {...React.ComponentPropsWithoutRef<'div'>}
265
- />
232
+ title="Click to expand"
233
+ className="custom-class"
234
+ styles={{
235
+ header: { backgroundColor: '#f3f4f6' },
236
+ content: { padding: '1rem' },
237
+ arrow: { color: '#6b7280' },
238
+ container: { marginBottom: '0.5rem' },
239
+ innerContent: { fontSize: '0.875rem' },
240
+ }}
241
+ >
242
+ <p>Accordion content goes here.</p>
243
+ </Accordion>
266
244
  ```
267
245
 
268
246
  **Props:**
269
- - `key: string` - Unique identifier for the accordion
270
- - `active: boolean` - Whether the accordion is expanded
271
- - `onClick: () => void` - Toggle function
272
- - `header: React.ReactNode` - Header content
273
- - `content: React.ReactNode` - Content to show when expanded
274
- - `className?: string` - Additional CSS classes for accordion
275
- - `containerClassName?: string` - CSS classes for accordion container element
276
- - `headerClassName?: string` - CSS classes for accordion header element
277
- - `contentClassName?: string` - CSS classes for accordion content element
278
- - `style?: React.CSSProperties` - Custom inline styles
279
- - `...props`: any - Additional HTML div attributes (spreads all native div props)
247
+ - `title: React.ReactNode` - Header title content
248
+ - `children: React.ReactNode` - Content to show when expanded
249
+ - `defaultActive?: boolean` - Whether expanded by default (default: false)
250
+ - `active?: boolean` - Controlled active state
251
+ - `onClick?: () => void` - Toggle click handler
252
+ - `styles?: Styles<'container' | 'header' | 'content' | 'arrow' | 'innerContent'>` - Custom inline styles per element
253
+ - `className?: string` - Additional CSS classes
280
254
 
281
255
  ### Spinner
282
256
  A loading spinner component with customizable types and animations.
@@ -285,19 +259,17 @@ A loading spinner component with customizable types and animations.
285
259
  <Spinner
286
260
  size="md"
287
261
  type="circle"
288
- className="text-blue-600"
289
- containerClassName="flex justify-center"
290
- dotClassName="w-2 h-2 bg-blue-600 rounded-full"
291
- barClassName="w-1 h-4 bg-blue-600 rounded-full"
292
- style={{ borderRadius: '50%' }}
262
+ color="#2563eb"
263
+ className="custom-class"
264
+ style={{ margin: '1rem' }}
293
265
  />
266
+ ```
267
+
294
268
  **Props:**
295
- - `className?: string` - Additional CSS classes
296
- - `containerClassName?: string` - CSS classes for container element
297
- - `dotClassName?: string` - CSS classes for dot elements
298
- - `barClassName?: string` - CSS classes for bar elements
299
269
  - `size?: SpinnerSize` - Spinner size (default: 'md')
300
270
  - `type?: SpinnerType` - Spinner animation type (default: 'circle')
271
+ - `color?: string` - Spinner color (default: '#2563eb')
272
+ - `className?: string` - Additional CSS classes
301
273
  - `style?: React.CSSProperties` - Custom inline styles
302
274
 
303
275
  **Types:**
@@ -311,36 +283,24 @@ A dropdown menu component with customizable toggle and options.
311
283
 
312
284
  ```jsx
313
285
  <DropDown
314
- toggle={
315
- <button className="bg-gray-100 hover:bg-gray-200 border border-gray-300 rounded px-3 py-2 text-sm">
316
- Menu
317
- </button>
318
- }
319
- options={[
320
- { value: 'option1', label: 'Option 1' },
321
- { value: 'option2', label: 'Option 2' },
322
- { value: 'option3', label: 'Option 3' }
323
- ]}
324
- selected="option1"
325
- onChange={(value) => console.log('Selected:', value)}
326
- className="relative inline-block text-left"
327
- dropdownClassName="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded shadow-lg z-10"
328
- optionsContainerClassName="py-1"
329
- optionClassName="block px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm"
286
+ options={['Option 1', 'Option 2', 'Option 3']}
287
+ value={selectedOption}
288
+ onChange={setSelectedOption}
289
+ placeholder="Select an option"
290
+ className="custom-dropdown"
330
291
  />
331
292
  ```
332
293
 
333
294
  **Props:**
334
- - `toggle: React.ReactNode` - Toggle button/element
335
- - `options: DropDownOption[]` - Array of option objects with `value` and `label` properties
336
- - `selected: string | number` - Currently selected option value
337
- - `onChange: (value: string | number) => void` - Selection change handler
295
+ - `options: (string | number | DropDownOption)[]` - Array of options
296
+ - `value?: string | number | React.ReactNode` - Currently selected value
297
+ - `onChange: (value: any) => void` - Selection change handler
298
+ - `placeholder?: string` - Placeholder text (default: 'Select an option')
299
+ - `toggle?: React.ReactNode` - Custom toggle element
300
+ - `classNames?: DropDownClassNames` - Custom class names for sub-elements
301
+ - `styles?: DropDownStyles` - Custom inline styles per element
302
+ - `disabled?: boolean` - Disable the dropdown (default: false)
338
303
  - `className?: string` - Additional CSS classes for container
339
- - `containerClassName?: string` - CSS classes for dropdown container element
340
- - `dropdownClassName?: string` - CSS classes for dropdown menu element
341
- - `optionsContainerClassName?: string` - CSS classes for options container element
342
- - `optionClassName?: string` - CSS classes for individual option elements
343
- - `style?: React.CSSProperties` - Custom inline styles
344
304
 
345
305
  **DropDownOption Interface:**
346
306
  ```typescript
@@ -351,29 +311,26 @@ interface DropDownOption {
351
311
  ```
352
312
 
353
313
  ### ProgressBar
354
- A progress bar component with customizable progress values and accessibility.
314
+ A progress bar component with customizable progress values, variants, and accessibility.
355
315
 
356
316
  ```jsx
357
317
  <ProgressBar
358
318
  progress={75}
359
- max={100}
360
- min={0}
361
- aria-label="Loading progress"
362
- className="bg-gray-200 rounded-full h-2"
363
- barClassName="bg-blue-600 h-full rounded-full transition-all duration-300"
319
+ variant="primary"
320
+ showPercentage
321
+ className="custom-class"
364
322
  />
365
323
  ```
366
324
 
367
325
  **Props:**
368
326
  - `progress: number` - Current progress value
369
- - `max: number` - Maximum progress value
370
- - `min: number` - Minimum progress value
371
- - `aria-label: string` - Accessibility label
372
- - `className?: React.CSSProperties` - Custom CSS properties for styling
373
- - `style?: React.CSSProperties` - Additional inline styles
374
- - `containerClassName?: string` - CSS classes for the container element
375
- - `barClassName?: string` - CSS classes for the progress bar element
327
+ - `max?: number` - Maximum progress value (default: 100)
328
+ - `min?: number` - Minimum progress value (default: 0)
376
329
  - `variant?: ProgressBarVariant` - Color variant (default: 'primary')
330
+ - `showPercentage?: boolean` - Show percentage text (default: true)
331
+ - `className?: string` - Additional CSS classes
332
+ - `styles?: { container?: React.CSSProperties; bar?: React.CSSProperties; text?: React.CSSProperties }` - Custom inline styles
333
+ - `aria-label?: string` - Accessibility label
377
334
 
378
335
  **Types:**
379
336
  ```typescript
@@ -391,15 +348,13 @@ A fullscreen overlay preloader component with customizable spinner and auto-hide
391
348
  accentColor="#00ff88"
392
349
  size={90}
393
350
  borderWidth={6}
394
- className="fixed inset-0 z-50"
395
- spinnerClassName="border-4 border-gray-300 border-t-green-400"
396
351
  onComplete={() => setIsLoading(false)}
397
352
  />
398
353
  ```
399
354
 
400
355
  **Props:**
401
356
  - `isLoading?: boolean` - Whether the preloader should be visible (if not provided, uses internal state)
402
- - `duration?: number` - Duration in milliseconds before auto-hide (default: 1000)
357
+ - `duration?: number` - Duration in milliseconds before auto-hide (default: 2000)
403
358
  - `backgroundColor?: string` - Background color of the overlay (default: CSS variable)
404
359
  - `accentColor?: string` - Color of the spinner (default: CSS variable)
405
360
  - `size?: number` - Size of the spinner in pixels (default: 60)
@@ -408,7 +363,7 @@ A fullscreen overlay preloader component with customizable spinner and auto-hide
408
363
  - `spinnerClassName?: string` - Additional CSS classes for the spinner
409
364
  - `zIndex?: number` - Z-index of the overlay (default: 999999)
410
365
  - `onComplete?: () => void` - Callback when preloader finishes
411
- - `style?: React.CSSProperties` - Custom inline styles
366
+ - `styles?: { overlay?: React.CSSProperties; spinner?: React.CSSProperties; }` - Custom inline styles
412
367
 
413
368
  **Usage Modes:**
414
369
  - **Controlled:** Use `isLoading` prop to control visibility externally
@@ -440,108 +395,24 @@ A floating scroll-to-top button that appears when the user scrolls down the page
440
395
  <ScrollTop
441
396
  threshold={200}
442
397
  position="bottom-right"
443
- size="md"
444
- className="bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow-lg"
398
+ className="custom-class"
445
399
  />
446
400
  ```
447
401
 
448
- **💡 Tip for Bootstrap / Existing CSS Frameworks:**
449
- If you are using this library in a project that also uses Bootstrap (or another framework), you may need to explicitly declare all Tailwind positioning and styling classes and mark them with `!` (important) to ensure they have priority over Bootstrap's default styles (which can override border-radius or positioning). For example:
450
-
451
- ```jsx
452
- <ScrollTop
453
- size="sm"
454
- scrollPercentage={5}
455
- className="!bg-indigo-600 hover:!bg-indigo-700 !text-white !rounded-full !z-[9999] !w-10 !h-10 flex items-center justify-center !right-8 !bottom-8 !fixed"
456
- position="bottom-right"
457
- >
458
- <i className="bi bi-arrow-up"></i>
459
- </ScrollTop>
460
- ```
461
-
462
402
  **Props:**
463
- - `threshold?: number` - Scroll position threshold to show the button in pixels (default: 100)
464
- - `className?: string` - Additional CSS classes for the button
465
- - `children?: React.ReactNode` - Custom icon/content for the button (default: arrow up)
466
- - `position?: 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center'` - Button position (default: 'bottom-right')
467
- - `size?: 'sm' | 'md' | 'lg'` - Button size (default: 'md')
468
- - `shape?: 'circle' | 'square' | 'rounded'` - Button shape (default: 'circle')
469
- - `showInitially?: boolean` - Whether to show the button initially (default: false)
403
+ - `threshold?: number` - Scroll position threshold in pixels (default: 100)
404
+ - `className?: string` - Additional CSS classes
405
+ - `children?: React.ReactNode` - Custom icon/content (default: arrow up SVG)
406
+ - `position?: CornerPosition` - Button position (default: 'bottom-right')
407
+ - `size?: number` - Button size in pixels (default: 48)
470
408
  - `scrollBehavior?: 'auto' | 'smooth'` - Scroll behavior (default: 'smooth')
471
- - `style?: React.CSSProperties` - Custom styles
472
- - `onClick?: () => void` - Callback when button is clicked
473
- - `onVisibilityChange?: (isVisible: boolean) => void` - Callback when visibility changes
474
- - `targetElement?: string` - Element ID or selector to check visibility for showing the button
475
- - `scrollPercentage?: number` - Percentage of page scroll to show the button (0-100)
476
- - `buttonClassName?: string` - CSS classes for the button element
477
- - `containerClassName?: string` - CSS classes for the container element
409
+ - `styles?: React.CSSProperties` - Custom inline styles
478
410
 
479
411
  **Position Options:**
480
412
  - `bottom-right` - Fixed bottom right
481
413
  - `bottom-left` - Fixed bottom left
482
- - `bottom-center` - Fixed bottom center
483
414
  - `top-right` - Fixed top right
484
415
  - `top-left` - Fixed top left
485
- - `top-center` - Fixed top center
486
-
487
- **Size Options:**
488
- - `sm` - Small (32x32px)
489
- - `md` - Medium (48x48px)
490
- - `lg` - Large (64x64px)
491
-
492
- **Shape Options:**
493
- - `circle` - Fully rounded
494
- - `square` - Square corners
495
- - `rounded` - Slightly rounded
496
-
497
- **Examples:**
498
- ```jsx
499
- // Default usage with target element
500
- <ScrollTop targetElement="#default-target" />
501
-
502
- // Custom position and size
503
- <ScrollTop
504
- position="bottom-left"
505
- size="lg"
506
- targetElement="#custom-target"
507
- className="bg-purple-600 hover:bg-purple-700"
508
- />
509
-
510
- // Top position with small size
511
- <ScrollTop
512
- position="top-right"
513
- size="sm"
514
- targetElement="#top-target"
515
- className="bg-green-600 hover:bg-green-700"
516
- />
517
-
518
- // Center position with custom color
519
- <ScrollTop
520
- position="top-center"
521
- size="sm"
522
- targetElement="#center-target"
523
- className="bg-blue-600 hover:bg-blue-700"
524
- />
525
-
526
- // Percentage-based triggering
527
- <ScrollTop
528
- position="bottom-center"
529
- size="lg"
530
- scrollPercentage={99}
531
- className="bg-indigo-600 hover:bg-indigo-700"
532
- >
533
- <span className="text-white font-bold">Top</span>
534
- </ScrollTop>
535
-
536
- // Custom icon with callbacks
537
- <ScrollTop
538
- targetElement="#footer"
539
- onVisibilityChange={(visible) => console.log('Visible:', visible)}
540
- onClick={() => console.log('Scrolled to top!')}
541
- >
542
- <span className="text-white font-bold">↑</span>
543
- </ScrollTop>
544
- ```
545
416
 
546
417
  ### Typed
547
418
  A typing animation component that types and deletes text in sequence.
@@ -552,33 +423,22 @@ A typing animation component that types and deletes text in sequence.
552
423
  typeSpeed={50}
553
424
  backSpeed={30}
554
425
  loop={true}
555
- className="text-blue-600 font-mono text-lg"
556
- containerClassName="inline-block"
557
- typedClassName="border-r-2 border-blue-600"
426
+ className="custom-class"
427
+ style={{ fontSize: '1.25rem' }}
558
428
  />
559
429
  ```
560
430
 
561
431
  **Props:**
562
432
  - `strings: string[]` - Array of strings to type in sequence
563
- - `typeSpeed?: number` - Speed of typing in milliseconds per character (default: 50)
564
- - `backSpeed?: number` - Speed of backspacing in milliseconds per character (default: 30)
565
- - `backDelay?: number` - Delay before backspacing starts in milliseconds (default: 500)
566
- - `startDelay?: number` - Delay before typing starts in milliseconds (default: 0)
567
- - `loop?: boolean` - Whether to loop through strings indefinitely (default: true)
568
- - `showCursor?: boolean` - Whether to show a blinking cursor (default: true)
569
- - `className?: string` - Additional CSS classes for the component
570
- - `containerClassName?: string` - CSS classes for the container element
571
- - `typedClassName?: string` - CSS classes for the typed text
572
- - `cursorClassName?: string` - CSS classes for the cursor
573
- - `style?: TypedStyle` - Custom CSS properties for styling
574
-
575
- **Types:**
576
- ```typescript
577
- type TypedStyle = CSSProperties & {
578
- animation?: string;
579
- animationDelay?: string;
580
- };
581
- ```
433
+ - `typeSpeed?: number` - Typing speed in ms per character (default: 50)
434
+ - `backSpeed?: number` - Backspacing speed in ms per character (default: 30)
435
+ - `backDelay?: number` - Delay before backspacing in ms (default: 500)
436
+ - `startDelay?: number` - Delay before typing starts in ms (default: 0)
437
+ - `loop?: boolean` - Loop through strings (default: true)
438
+ - `showCursor?: boolean` - Show blinking cursor (default: true)
439
+ - `className?: string` - Additional CSS classes
440
+ - `style?: CSSProperties & { animation?: string; animationDelay?: string }` - Custom inline styles
441
+ - `cursorStyle?: React.CSSProperties` - Custom styles for cursor element
582
442
 
583
443
  ### WhatsApp
584
444
  A WhatsApp button component for quick contact integration.
@@ -589,28 +449,21 @@ A WhatsApp button component for quick contact integration.
589
449
  message="Hello! I need help."
590
450
  position="bottom-right"
591
451
  size="md"
592
- className="bg-green-500 hover:bg-green-600 text-white rounded-full shadow-lg"
452
+ className="custom-class"
593
453
  />
594
454
  ```
595
455
 
596
456
  **Props:**
597
- - `phone?: string` - Phone number for WhatsApp (with country code, without + or spaces)
598
- - `message?: string` - Default message to send (default: "¡Hola! Me gustaría obtener más información.")
599
- - `position?: WhatsAppPosition` - Position of the button (default: 'bottom-right')
600
- - `size?: WhatsAppSize` - Size of the button (default: 'md')
457
+ - `phone?: string` - Phone number (with country code, without + or spaces)
458
+ - `message?: string` - Default message (default: 'Hi!')
459
+ - `position?: CornerPosition` - Button position (default: 'bottom-right')
460
+ - `size?: Size` - Button size (default: 'md')
601
461
  - `showTooltip?: boolean` - Show tooltip on hover (default: true)
602
- - `tooltipText?: string` - Tooltip text
603
- - `className?: string` - Additional CSS classes for the button
604
- - `style?: React.CSSProperties` - Custom styles
605
- - `onClick?: () => void` - Callback when button is clicked
606
- - `zIndex?: number` - Z-index for the button
607
- - `openInNewTab?: boolean` - Whether to open in new tab (default: true)
608
-
609
- **Types:**
610
- ```typescript
611
- type WhatsAppPosition = 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';
612
- type WhatsAppSize = 'sm' | 'md' | 'lg';
613
- ```
462
+ - `tooltipText?: string` - Tooltip text (default: 'Need help?')
463
+ - `className?: string` - Additional CSS classes
464
+ - `styles?: { button?: React.CSSProperties; tooltip?: React.CSSProperties }` - Custom inline styles
465
+ - `onClick?: () => void` - Click callback
466
+ - `zIndex?: number` - Z-index (default: 1000)
614
467
 
615
468
  ### Modal
616
469
  A flexible modal component for displaying dialogs, forms, and overlays.
@@ -653,13 +506,14 @@ A flexible modal component for displaying dialogs, forms, and overlays.
653
506
  - `footer?: React.ReactNode` - Custom footer content
654
507
  - `closeButton?: boolean` - Whether to show close button (default: true)
655
508
  - `className?: string` - Additional CSS classes for the modal
656
- - `dialogClassName?: string` - CSS classes for the modal dialog
657
- - `contentClassName?: string` - CSS classes for the modal content
658
- - `headerClassName?: string` - CSS classes for the modal header
659
- - `bodyClassName?: string` - CSS classes for the modal body
660
- - `footerClassName?: string` - CSS classes for the modal footer
509
+ - `dialogClassName?: string` - CSS classes for the modal dialog (default: 'luna-modal-dialog')
510
+ - `contentClassName?: string` - CSS classes for the modal content (default: 'luna-modal-content')
511
+ - `headerClassName?: string` - CSS classes for the modal header (default: 'luna-modal-header')
512
+ - `bodyClassName?: string` - CSS classes for the modal body (default: 'luna-modal-body')
513
+ - `footerClassName?: string` - CSS classes for the modal footer (default: 'luna-modal-footer')
661
514
  - `style?: React.CSSProperties` - Custom inline styles
662
515
 
516
+
663
517
  **Types:**
664
518
  ```typescript
665
519
  type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
@@ -772,7 +626,7 @@ const MyComponent = () => {
772
626
  ```
773
627
 
774
628
  ### Input
775
- A versatile input component with multiple variants, sizes, and types.
629
+ A versatile input component with multiple variants, sizes, masks, currency formatting, and types.
776
630
 
777
631
  ```jsx
778
632
  <Input
@@ -782,8 +636,11 @@ A versatile input component with multiple variants, sizes, and types.
782
636
  placeholder="Enter your text here"
783
637
  value={inputValue}
784
638
  onChange={(value) => setInputValue(value)}
785
- className="border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
786
- />
639
+ className="custom-class"
640
+ id="my-input"
641
+ >
642
+ Input Label
643
+ </Input>
787
644
  ```
788
645
 
789
646
  **Props:**
@@ -800,15 +657,21 @@ A versatile input component with multiple variants, sizes, and types.
800
657
  - `required?: boolean` - Required field (default: false)
801
658
  - `readOnly?: boolean` - Read-only input (default: false)
802
659
  - `className?: string` - Additional CSS classes
803
- - `containerClassName?: string` - CSS classes for container element
804
- - `inputClassName?: string` - CSS classes for input element
805
- - `variantClassName?: string` - CSS classes for variant styling
806
- - `sizeClassName?: string` - CSS classes for size styling
807
660
  - `style?: React.CSSProperties` - Custom inline styles
808
661
  - `id?: string` - HTML id attribute for label association
662
+ - `name?: string` - HTML name attribute
663
+ - `classNames?: InputClassNames` - Custom class names for sub-elements
664
+ - `styles?: InputStyles` - Custom inline styles per element
665
+ - `mask?: string` - Input mask pattern (e.g. "(999) 999-9999")
666
+ - `maskChar?: string` - Mask placeholder character (default: '_')
667
+ - `useCurrency?: boolean` - Enable currency formatting
668
+ - `currency?: string` - Currency code (e.g. "USD", "CRC")
669
+ - `locale?: string` - Locale for formatting (e.g. "en-US", "es-CR")
670
+ - `minFractionDigits?: number` - Minimum fraction digits (default: 0)
671
+ - `maxFractionDigits?: number` - Maximum fraction digits (default: 2)
809
672
  - `aria-label?: string` - ARIA label for accessibility
810
- - `aria-labelledby?: string` - ARIA labelledby for accessibility
811
- - `...props`: any - Additional HTML input attributes (spreads all native input props)
673
+ - `aria-labelledby?: string` - ARIA labelledby
674
+ - `...props`: any - Additional HTML input attributes
812
675
 
813
676
  **Types:**
814
677
  ```typescript
@@ -819,17 +682,85 @@ type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'sea
819
682
 
820
683
  **Variants:**
821
684
  - `none` - Default styling with border
822
- - `primary` - Blue background with white text
823
- - `secondary` - Gray background with white text
824
- - `outline` - Border only with gray text
825
- - `danger` - Red background with white text
826
- - `success` - Green background with white text
685
+ - `primary` - Blue focus ring
686
+ - `secondary` - Gray focus ring
687
+ - `outline` - Border only
688
+ - `danger` - Red focus ring
689
+ - `success` - Green focus ring
827
690
 
828
691
  **Size Options:**
829
692
  - `sm` - Small padding and text
830
693
  - `md` - Medium padding and text
831
694
  - `lg` - Large padding and text
832
695
  - `xl` - Extra large padding and text
696
+ ### DataTable
697
+ A powerful and customizable data grid with support for filtering, sorting, pagination, selection, and search.
698
+
699
+ ```jsx
700
+ <DataTable
701
+ columns={[
702
+ { key: 'name', label: 'Name', sortable: true, filterable: true },
703
+ { key: 'email', label: 'Email' },
704
+ {
705
+ key: 'status',
706
+ label: 'Status',
707
+ filterable: true,
708
+ filterOptions: [
709
+ { label: 'Active', value: 'Active' },
710
+ { label: 'Inactive', value: 'Inactive' }
711
+ ],
712
+ render: (val) => <span className={val === 'Active' ? 'text-green-600' : 'text-red-600'}>{val}</span>
713
+ },
714
+ {
715
+ key: 'actions',
716
+ label: 'Actions',
717
+ render: (_, row) => (
718
+ <Button size="sm" variant="outline" onClick={() => handleEdit(row)}>
719
+ Edit
720
+ </Button>
721
+ )
722
+ }
723
+ ]}
724
+ data={myData}
725
+ pagination
726
+ pageSize={5}
727
+ selectable
728
+ searchable
729
+ onRowClick={(row) => console.log('Clicked:', row)}
730
+ onSelectionChange={(selectedRows) => console.log('Selected:', selectedRows)}
731
+ className="custom-datatable"
732
+ />
733
+ ```
734
+
735
+ **Props:**
736
+ - `columns: DataTableColumn[]` - Array of column definitions
737
+ - `data: any[]` - Array of data objects
738
+ - `pagination?: boolean` - Enable pagination (default: false)
739
+ - `pageSize?: number` - Rows per page (default: 10)
740
+ - `selectable?: boolean` - Show selection checkboxes (default: false)
741
+ - `searchable?: boolean` - Show search filter (default: false)
742
+ - `onSelectionChange?: (selectedRows: any[]) => void` - Selection change handler
743
+ - `onRowClick?: (row: any) => void` - Row click handler
744
+ - `onRowDoubleClick?: (row: any) => void` - Row double click handler
745
+ - `texts?: DataTableTexts` - Custom text labels for i18n
746
+ - `classNames?: DataTableClassNames` - Custom class names per element
747
+ - `styles?: DataTableStyles` - Custom inline styles per element
748
+ - `className?: string` - Additional CSS classes
749
+
750
+ **Column Interface:**
751
+ ```typescript
752
+ interface DataTableColumn {
753
+ key: string;
754
+ label: React.ReactNode;
755
+ sortable?: boolean;
756
+ filterable?: boolean;
757
+ filterOptions?: { label: string; value: any }[];
758
+ render?: (value: any, row: any) => React.ReactNode;
759
+ }
760
+ ```
761
+
762
+
763
+
833
764
 
834
765
 
835
766
  ## 🛠️ Utilities & Hooks
@@ -837,7 +768,7 @@ type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'sea
837
768
  Luna Library now includes generic utilities and hooks to streamline API communication and state management.
838
769
 
839
770
  ### 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.
771
+ 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
772
 
842
773
  ```javascript
843
774
  import { httpClient } from 'luna-components-library';
@@ -854,6 +785,21 @@ const response = await httpClient.post('https://api.example.com/posts', {
854
785
  // httpClient.delete(url, options)
855
786
  ```
856
787
 
788
+ ### apiFetch
789
+ A low-level wrapper for the native `fetch` API that includes automatic response parsing and error handling for non-OK HTTP statuses.
790
+
791
+ ```javascript
792
+ import { apiFetch } from 'luna-components-library';
793
+
794
+ try {
795
+ const data = await apiFetch('https://api.example.com/resource');
796
+ console.log(data);
797
+ } catch (error) {
798
+ console.error('Fetch failed:', error.message);
799
+ }
800
+ ```
801
+
802
+
857
803
  ### storage
858
804
  A wrapper for `localStorage` with safety checks and automatic JSON parsing.
859
805
 
@@ -900,7 +846,6 @@ logger.success('User logged in');
900
846
  logger.warn('Low disk space');
901
847
  logger.error('API failed', error);
902
848
  ```
903
- ```
904
849
 
905
850
  ### useFetch
906
851
  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 +871,7 @@ function UserList() {
926
871
  </ul>
927
872
  );
928
873
  }
874
+ ```
929
875
 
930
876
  ### useLocalStorage
931
877
  Syncs state with `localStorage` automatically.
@@ -993,8 +939,12 @@ luna-library/
993
939
  │ │ ├── utilExamples/ # Examples for hooks and extra utilities
994
940
  │ │ ├── Button.tsx
995
941
  │ │ ├── Card.tsx
942
+ │ │ ├── DataTable.tsx
996
943
  │ │ ├── ... (Other UI Components)
944
+
997
945
  │ │ └── index.ts
946
+ │ ├── styles.ts # Design tokens and shared style functions
947
+ │ ├── types.ts # Shared TypeScript types
998
948
  │ ├── hooks/
999
949
  │ │ ├── useFetch.hook.ts
1000
950
  │ │ ├── useLocalStorage.hook.ts
@@ -1074,7 +1024,9 @@ The library is configured with:
1074
1024
  - `rimraf` - Cross-platform file removal
1075
1025
 
1076
1026
  ### Styling
1077
- This library is built with **Tailwind CSS** utility classes. Components use predefined Tailwind classes for consistent styling and are fully customizable through the `className` prop.
1027
+ This library uses a **pure inline-style architecture** with a centralized design system. All design tokens (`colors`, `radii`, `fontSizes`, `shadows`, `transitions`, etc.) and shared style objects (`commonStyles`, `variantStyles`, `sizeStyles`) are defined in `src/styles.ts`. Components consume these tokens and generate inline styles, class name strings, or both depending on the component.
1028
+
1029
+ **No CSS framework required** - you don't need Tailwind CSS, PostCSS, or any other styling tool to use this library. Each component accepts `className` (for CSS classes) and `style` (for inline style overrides) props for customization.
1078
1030
 
1079
1031
  ## 🤝 Contributing
1080
1032