@diniz/webcomponents 1.0.2 → 1.0.3

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.
Files changed (2) hide show
  1. package/README.md +490 -9
  2. package/package.json +2 -1
package/README.md CHANGED
@@ -12,12 +12,170 @@ A lightweight, framework-agnostic web components library built with vanilla Type
12
12
  🎯 **Tree-shakeable** - Import only what you need
13
13
  ♿ **Accessible** - ARIA attributes and keyboard navigation
14
14
 
15
+ ## 🚀 Live Demo
16
+
17
+ Check out the interactive demo and component examples:
18
+
19
+ **[View Live Demo →](https://rodiniz.github.io/webcomponents/)**
20
+
15
21
  ## Installation
16
22
 
17
23
  ```bash
18
24
  npm install @diniz/webcomponents
19
25
  ```
20
26
 
27
+ ## Using with Vite (No Framework)
28
+
29
+ This library works seamlessly with Vite without requiring any framework. Here's how to set up a vanilla JavaScript/TypeScript project:
30
+
31
+ ### 1. Create a New Vite Project
32
+
33
+ ```bash
34
+ # Create a new Vite project with vanilla TypeScript template
35
+ npm create vite@latest my-app -- --template vanilla-ts
36
+ cd my-app
37
+ npm install
38
+ ```
39
+
40
+ ### 2. Install the Library
41
+
42
+ ```bash
43
+ npm install @diniz/webcomponents
44
+ ```
45
+
46
+ ### 3. Import Components in Your Main File
47
+
48
+ In your `src/main.ts` file:
49
+
50
+ ```typescript
51
+ import '@diniz/webcomponents';
52
+ import '@diniz/webcomponents/dist/style.css'; // Import styles
53
+
54
+ // Now you can use the components in your HTML
55
+ document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
56
+ <div>
57
+ <h1>My Web Components App</h1>
58
+ <ui-button variant="primary" size="md">Click Me</ui-button>
59
+ <ui-date-picker format="DD/MM/YYYY"></ui-date-picker>
60
+ </div>
61
+ `;
62
+ ```
63
+
64
+ ### 4. Use Components in HTML
65
+
66
+ In your `index.html`:
67
+
68
+ ```html
69
+ <!DOCTYPE html>
70
+ <html lang="en">
71
+ <head>
72
+ <meta charset="UTF-8" />
73
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
74
+ <title>My App</title>
75
+ </head>
76
+ <body>
77
+ <div id="app">
78
+ <ui-button variant="primary">Click Me</ui-button>
79
+ <ui-date-picker format="DD/MM/YYYY"></ui-date-picker>
80
+ <ui-table></ui-table>
81
+ </div>
82
+ <script type="module" src="/src/main.ts"></script>
83
+ </body>
84
+ </html>
85
+ ```
86
+
87
+ ### 5. Add Event Listeners (Optional)
88
+
89
+ ```typescript
90
+ // Wait for components to be defined
91
+ customElements.whenDefined('ui-button').then(() => {
92
+ const button = document.querySelector('ui-button');
93
+ button?.addEventListener('click', () => {
94
+ console.log('Button clicked!');
95
+ });
96
+ });
97
+
98
+ // Listen to custom events
99
+ const picker = document.querySelector('ui-date-picker');
100
+ picker?.addEventListener('date-change', ((e: CustomEvent) => {
101
+ console.log('Date selected:', e.detail.value);
102
+ }) as EventListener);
103
+ ```
104
+
105
+ ### 6. TypeScript Support
106
+
107
+ For full TypeScript support, create a `src/types.d.ts` file:
108
+
109
+ ```typescript
110
+ declare module '@diniz/webcomponents' {
111
+ export interface UIButton extends HTMLElement {
112
+ variant: 'primary' | 'secondary' | 'ghost';
113
+ size: 'sm' | 'md' | 'lg';
114
+ icon?: string;
115
+ disabled?: boolean;
116
+ }
117
+
118
+ export interface UIDatePicker extends HTMLElement {
119
+ format: string;
120
+ value: string;
121
+ min?: string;
122
+ max?: string;
123
+ }
124
+
125
+ // Add other component interfaces as needed
126
+ }
127
+
128
+ declare global {
129
+ interface HTMLElementTagNameMap {
130
+ 'ui-button': import('@diniz/webcomponents').UIButton;
131
+ 'ui-date-picker': import('@diniz/webcomponents').UIDatePicker;
132
+ // Add other components as needed
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### 7. Build for Production
138
+
139
+ ```bash
140
+ npm run build
141
+ ```
142
+
143
+ The build output will be in the `dist` folder, ready to deploy to any static hosting service.
144
+
145
+ ### Tree-shaking (Import Only What You Need)
146
+
147
+ You can import individual components to reduce bundle size:
148
+
149
+ ```typescript
150
+ // Import only specific components
151
+ import { UIButton } from '@diniz/webcomponents';
152
+ import '@diniz/webcomponents/dist/style.css';
153
+
154
+ // The component is automatically registered
155
+ // Now you can use <ui-button> in your HTML
156
+ ```
157
+
158
+ ### Configuration Tips
159
+
160
+ **Vite Config** - No special configuration needed! Web Components work out of the box with Vite.
161
+
162
+ **CSS Customization** - Override CSS custom properties to match your theme:
163
+
164
+ ```css
165
+ :root {
166
+ --color-primary: #3b82f6;
167
+ --color-secondary: #8b5cf6;
168
+ --color-success: #10b981;
169
+ --color-danger: #ef4444;
170
+ --color-warning: #f59e0b;
171
+ --color-info: #06b6d4;
172
+
173
+ --radius-sm: 0.25rem;
174
+ --radius-md: 0.375rem;
175
+ --radius-lg: 0.5rem;
176
+ }
177
+ ```
178
+
21
179
  ## Quick Start
22
180
 
23
181
  ```html
@@ -34,11 +192,14 @@ npm install @diniz/webcomponents
34
192
 
35
193
  ### 🔘 Button (`ui-button`)
36
194
 
37
- A versatile button component with multiple variants and sizes.
195
+ A versatile button component with multiple variants, sizes, and icon support.
38
196
 
39
197
  **Features:**
40
198
  - 3 variants: `primary`, `secondary`, `ghost`
41
199
  - 3 sizes: `sm`, `md`, `lg`
200
+ - Icon support with [Feather Icons](https://feathericons.com/)
201
+ - Icon positioning (left/right)
202
+ - Icon-only buttons
42
203
  - Disabled state support
43
204
  - Button type support
44
205
  - Smooth transitions and hover effects
@@ -48,11 +209,18 @@ A versatile button component with multiple variants and sizes.
48
209
  <ui-button variant="primary" size="md">Primary Button</ui-button>
49
210
  <ui-button variant="secondary" size="sm">Secondary</ui-button>
50
211
  <ui-button variant="ghost" disabled>Disabled</ui-button>
212
+
213
+ <!-- With icons -->
214
+ <ui-button variant="primary" icon="check">Save</ui-button>
215
+ <ui-button variant="secondary" icon="trash-2" icon-position="right">Delete</ui-button>
216
+ <ui-button variant="ghost" icon="settings"></ui-button>
51
217
  ```
52
218
 
53
219
  **Attributes:**
54
220
  - `variant` - Button style (`primary` | `secondary` | `ghost`)
55
221
  - `size` - Button size (`sm` | `md` | `lg`)
222
+ - `icon` - Icon name from Feather Icons
223
+ - `icon-position` - Icon position (`left` | `right`, default: `left`)
56
224
  - `disabled` - Disable the button
57
225
  - `type` - Button type (`button` | `submit` | `reset`)
58
226
 
@@ -250,6 +418,198 @@ Advanced form input with built-in validation and error handling.
250
418
 
251
419
  ---
252
420
 
421
+ ### 🪟 Modal (`ui-modal`)
422
+
423
+ Responsive modal dialog with customizable sizes and behaviors.
424
+
425
+ **Features:**
426
+ - 5 size options: `sm`, `md`, `lg`, `xl`, `full`
427
+ - Auto-close on Escape key (configurable)
428
+ - Auto-close on backdrop click (configurable)
429
+ - Smooth animations (fade in, slide up)
430
+ - Header, body, and footer slots
431
+ - Programmatic open/close API
432
+ - Custom events
433
+ - Body scroll lock when open
434
+
435
+ **Usage:**
436
+ ```html
437
+ <ui-button id="openModal">Open Modal</ui-button>
438
+
439
+ <ui-modal id="myModal" title="Welcome!" size="md">
440
+ <p>This is the modal content.</p>
441
+ <p>You can include any HTML here.</p>
442
+
443
+ <div slot="footer">
444
+ <ui-button id="closeBtn" variant="secondary">Cancel</ui-button>
445
+ <ui-button id="confirmBtn" variant="primary">Confirm</ui-button>
446
+ </div>
447
+ </ui-modal>
448
+
449
+ <script>
450
+ const modal = document.getElementById('myModal');
451
+ const openBtn = document.getElementById('openModal');
452
+ const closeBtn = document.getElementById('closeBtn');
453
+
454
+ openBtn.addEventListener('click', () => modal.open());
455
+ closeBtn.addEventListener('click', () => modal.close());
456
+
457
+ modal.addEventListener('modal-close', () => {
458
+ console.log('Modal closed');
459
+ });
460
+ </script>
461
+ ```
462
+
463
+ **Attributes:**
464
+ - `title` - Modal title text
465
+ - `size` - Modal size (`sm` | `md` | `lg` | `xl` | `full`)
466
+ - `open` - Open state attribute
467
+ - `no-close-on-escape` - Disable closing on Escape key
468
+ - `no-close-on-backdrop` - Disable closing on backdrop click
469
+
470
+ **Methods:**
471
+ - `open()` - Open the modal
472
+ - `close()` - Close the modal
473
+
474
+ **Events:**
475
+ - `modal-open` - Fired when modal opens
476
+ - `modal-close` - Fired when modal closes
477
+
478
+ ---
479
+
480
+ ### 📋 Select (`ui-select`)
481
+
482
+ Customizable dropdown select with search capability.
483
+
484
+ **Features:**
485
+ - JSON-based options configuration
486
+ - Searchable dropdown (optional)
487
+ - Keyboard navigation
488
+ - Disabled options support
489
+ - Custom placeholder text
490
+ - Change events with full option details
491
+ - Click-outside to close
492
+ - Smooth animations
493
+ - Theme-aware styling
494
+
495
+ **Usage:**
496
+ ```html
497
+ <ui-select
498
+ id="mySelect"
499
+ label="Choose a Country"
500
+ placeholder="Select country..."
501
+ searchable
502
+ ></ui-select>
503
+
504
+ <script>
505
+ const select = document.getElementById('mySelect');
506
+
507
+ // Set options
508
+ const options = [
509
+ { value: 'us', label: 'United States' },
510
+ { value: 'uk', label: 'United Kingdom' },
511
+ { value: 'ca', label: 'Canada' },
512
+ { value: 'au', label: 'Australia', disabled: true }
513
+ ];
514
+
515
+ select.setAttribute('options', JSON.stringify(options));
516
+
517
+ // Set initial value
518
+ select.setAttribute('value', 'us');
519
+
520
+ // Listen for changes
521
+ select.addEventListener('select-change', (e) => {
522
+ console.log('Value:', e.detail.value);
523
+ console.log('Option:', e.detail.option);
524
+ });
525
+ </script>
526
+ ```
527
+
528
+ **Attributes:**
529
+ - `label` - Label text above select
530
+ - `placeholder` - Placeholder when no selection
531
+ - `options` - JSON string of options array
532
+ - `value` - Currently selected value
533
+ - `disabled` - Disable the select
534
+ - `searchable` - Enable search functionality
535
+
536
+ **Option Format:**
537
+ ```typescript
538
+ {
539
+ value: string; // The option value
540
+ label: string; // Display text
541
+ disabled?: boolean; // Optional: disable option
542
+ }
543
+ ```
544
+
545
+ **Events:**
546
+ - `select-change` - Fired when selection changes
547
+ - `detail.value` - Selected value
548
+ - `detail.option` - Full option object
549
+
550
+ ---
551
+
552
+ ### ☑️ Checkbox (`ui-checkbox`)
553
+
554
+ Flexible checkbox with indeterminate state support.
555
+
556
+ **Features:**
557
+ - 3 sizes: `sm`, `md`, `lg`
558
+ - Checked/unchecked states
559
+ - Indeterminate state (useful for "select all")
560
+ - Disabled state
561
+ - Label support (attribute or slot)
562
+ - Programmatic API
563
+ - Custom events
564
+ - Smooth animations and transitions
565
+ - Theme-aware styling
566
+
567
+ **Usage:**
568
+ ```html
569
+ <!-- Basic usage -->
570
+ <ui-checkbox label="Accept terms"></ui-checkbox>
571
+ <ui-checkbox label="Subscribe" checked></ui-checkbox>
572
+ <ui-checkbox label="Disabled" disabled></ui-checkbox>
573
+
574
+ <!-- With sizes -->
575
+ <ui-checkbox label="Small" size="sm"></ui-checkbox>
576
+ <ui-checkbox label="Medium" size="md"></ui-checkbox>
577
+ <ui-checkbox label="Large" size="lg"></ui-checkbox>
578
+
579
+ <!-- Programmatic usage -->
580
+ <ui-checkbox id="myCheckbox" label="Select All"></ui-checkbox>
581
+
582
+ <script>
583
+ const checkbox = document.getElementById('myCheckbox');
584
+
585
+ // Listen for changes
586
+ checkbox.addEventListener('checkbox-change', (e) => {
587
+ console.log('Checked:', e.detail.checked);
588
+ });
589
+
590
+ // Set states programmatically
591
+ checkbox.setChecked(true);
592
+ checkbox.setIndeterminate(true);
593
+ </script>
594
+ ```
595
+
596
+ **Attributes:**
597
+ - `label` - Label text
598
+ - `checked` - Checked state
599
+ - `indeterminate` - Indeterminate state
600
+ - `disabled` - Disable checkbox
601
+ - `size` - Checkbox size (`sm` | `md` | `lg`)
602
+
603
+ **Methods:**
604
+ - `setChecked(checked: boolean)` - Set checked state
605
+ - `setIndeterminate(indeterminate: boolean)` - Set indeterminate state
606
+
607
+ **Events:**
608
+ - `checkbox-change` - Fired when state changes
609
+ - `detail.checked` - New checked state
610
+
611
+ ---
612
+
253
613
  ### 🎯 Sidebar (`app-sidebar`)
254
614
 
255
615
  Navigation sidebar component with links.
@@ -406,9 +766,12 @@ src/
406
766
  ├── shared/
407
767
  │ └── components/ # Reusable UI components
408
768
  │ ├── button.ts
769
+ │ ├── checkbox.ts
409
770
  │ ├── date-picker.ts
410
771
  │ ├── input.ts
772
+ │ ├── modal.ts
411
773
  │ ├── pagination.ts
774
+ │ ├── select.ts
412
775
  │ └── table.ts
413
776
  ├── layouts/
414
777
  │ └── app-layout.ts # Application shell
@@ -498,6 +861,131 @@ src/
498
861
  </script>
499
862
  ```
500
863
 
864
+ ### Confirmation Modal
865
+
866
+ ```html
867
+ <ui-button id="deleteBtn" variant="primary" icon="trash-2">
868
+ Delete Item
869
+ </ui-button>
870
+
871
+ <ui-modal id="confirmModal" title="Confirm Delete" size="sm">
872
+ <p>Are you sure you want to delete this item?</p>
873
+ <p style="color: #ef4444;">This action cannot be undone.</p>
874
+
875
+ <div slot="footer">
876
+ <ui-button id="cancelBtn" variant="ghost">Cancel</ui-button>
877
+ <ui-button id="confirmBtn" variant="primary">Delete</ui-button>
878
+ </div>
879
+ </ui-modal>
880
+
881
+ <script>
882
+ const deleteBtn = document.getElementById('deleteBtn');
883
+ const modal = document.getElementById('confirmModal');
884
+ const cancelBtn = document.getElementById('cancelBtn');
885
+ const confirmBtn = document.getElementById('confirmBtn');
886
+
887
+ deleteBtn.addEventListener('click', () => modal.open());
888
+ cancelBtn.addEventListener('click', () => modal.close());
889
+ confirmBtn.addEventListener('click', () => {
890
+ // Perform delete action
891
+ console.log('Item deleted');
892
+ modal.close();
893
+ });
894
+ </script>
895
+ ```
896
+
897
+ ### Dynamic Form with Select
898
+
899
+ ```html
900
+ <form id="userForm">
901
+ <ui-select
902
+ id="roleSelect"
903
+ label="User Role"
904
+ placeholder="Select role..."
905
+ ></ui-select>
906
+
907
+ <ui-select
908
+ id="countrySelect"
909
+ label="Country"
910
+ placeholder="Select country..."
911
+ searchable
912
+ ></ui-select>
913
+
914
+ <ui-button type="submit" variant="primary" icon="check">
915
+ Create User
916
+ </ui-button>
917
+ </form>
918
+
919
+ <script>
920
+ const roleSelect = document.getElementById('roleSelect');
921
+ const countrySelect = document.getElementById('countrySelect');
922
+
923
+ // Set options
924
+ roleSelect.setAttribute('options', JSON.stringify([
925
+ { value: 'admin', label: 'Administrator' },
926
+ { value: 'user', label: 'User' },
927
+ { value: 'guest', label: 'Guest' }
928
+ ]));
929
+
930
+ countrySelect.setAttribute('options', JSON.stringify([
931
+ { value: 'us', label: 'United States' },
932
+ { value: 'uk', label: 'United Kingdom' },
933
+ { value: 'ca', label: 'Canada' }
934
+ ]));
935
+
936
+ document.getElementById('userForm').addEventListener('submit', (e) => {
937
+ e.preventDefault();
938
+ const role = roleSelect.getAttribute('value');
939
+ const country = countrySelect.getAttribute('value');
940
+ console.log({ role, country });
941
+ });
942
+ </script>
943
+ ```
944
+
945
+ ### Select All with Checkboxes
946
+
947
+ ```html
948
+ <ui-checkbox id="selectAll" label="Select All"></ui-checkbox>
949
+
950
+ <div style="margin-left: 2rem;">
951
+ <ui-checkbox class="item" label="Item 1" size="sm"></ui-checkbox>
952
+ <ui-checkbox class="item" label="Item 2" size="sm"></ui-checkbox>
953
+ <ui-checkbox class="item" label="Item 3" size="sm"></ui-checkbox>
954
+ </div>
955
+
956
+ <script>
957
+ const selectAll = document.getElementById('selectAll');
958
+ const items = document.querySelectorAll('.item');
959
+
960
+ // Update select all based on items
961
+ function updateSelectAll() {
962
+ const checkedCount = Array.from(items).filter(
963
+ item => item.hasAttribute('checked')
964
+ ).length;
965
+
966
+ if (checkedCount === 0) {
967
+ selectAll.setChecked(false);
968
+ } else if (checkedCount === items.length) {
969
+ selectAll.setChecked(true);
970
+ } else {
971
+ selectAll.setIndeterminate(true);
972
+ }
973
+ }
974
+
975
+ // Handle select all click
976
+ selectAll.addEventListener('checkbox-change', (e) => {
977
+ items.forEach(item => item.setChecked(e.detail.checked));
978
+ });
979
+
980
+ // Handle individual item clicks
981
+ items.forEach(item => {
982
+ item.addEventListener('checkbox-change', updateSelectAll);
983
+ });
984
+
985
+ updateSelectAll();
986
+ </script>
987
+ ```
988
+
501
989
  ---
502
990
 
503
991
  ## Contributing
@@ -508,13 +996,6 @@ Contributions are welcome! Please feel free to submit a Pull Request.
508
996
 
509
997
  ## License
510
998
 
511
- MIT © [Your Name]
512
-
513
- ---
999
+ MIT © Rodrigo Diniz
514
1000
 
515
- ## Links
516
1001
 
517
- - [Demo](https://your-demo-url.com)
518
- - [Documentation](https://your-docs-url.com)
519
- - [GitHub](https://github.com/yourusername/webcomponents)
520
- - [npm](https://www.npmjs.com/package/@diniz/webcomponents)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diniz/webcomponents",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Lightweight web components library",
5
5
  "type": "module",
6
6
  "main": "./dist/webcomponents.umd.js",
@@ -25,6 +25,7 @@
25
25
  "preview:prod": "vite preview --port 4173"
26
26
  },
27
27
  "devDependencies": {
28
+ "@types/feather-icons": "^4.29.4",
28
29
  "@types/node": "^25.3.1",
29
30
  "typescript": "^5.4.0",
30
31
  "vite": "^5.2.0"