@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.
- package/README.md +490 -9
- 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
|
|
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 ©
|
|
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.
|
|
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"
|