@diniz/webcomponents 1.0.0 → 1.0.2
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 +520 -0
- package/package.json +7 -2
package/README.md
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
# @diniz/webcomponents
|
|
2
|
+
|
|
3
|
+
A lightweight, framework-agnostic web components library built with vanilla TypeScript. Create modern, reactive UIs using native Web Components API with zero dependencies.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
✨ **Native Web Components** - Built on standard Custom Elements API
|
|
8
|
+
⚡ **Reactive Signals** - Built-in signal-based reactivity system
|
|
9
|
+
🎨 **Theme Support** - CSS custom properties for easy theming
|
|
10
|
+
📦 **Zero Dependencies** - No framework required
|
|
11
|
+
🔒 **TypeScript** - Full type safety and IntelliSense support
|
|
12
|
+
🎯 **Tree-shakeable** - Import only what you need
|
|
13
|
+
♿ **Accessible** - ARIA attributes and keyboard navigation
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @diniz/webcomponents
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<script type="module">
|
|
25
|
+
import '@diniz/webcomponents';
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<ui-button variant="primary">Click Me</ui-button>
|
|
29
|
+
<ui-date-picker format="DD/MM/YYYY"></ui-date-picker>
|
|
30
|
+
<ui-table></ui-table>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Components
|
|
34
|
+
|
|
35
|
+
### 🔘 Button (`ui-button`)
|
|
36
|
+
|
|
37
|
+
A versatile button component with multiple variants and sizes.
|
|
38
|
+
|
|
39
|
+
**Features:**
|
|
40
|
+
- 3 variants: `primary`, `secondary`, `ghost`
|
|
41
|
+
- 3 sizes: `sm`, `md`, `lg`
|
|
42
|
+
- Disabled state support
|
|
43
|
+
- Button type support
|
|
44
|
+
- Smooth transitions and hover effects
|
|
45
|
+
|
|
46
|
+
**Usage:**
|
|
47
|
+
```html
|
|
48
|
+
<ui-button variant="primary" size="md">Primary Button</ui-button>
|
|
49
|
+
<ui-button variant="secondary" size="sm">Secondary</ui-button>
|
|
50
|
+
<ui-button variant="ghost" disabled>Disabled</ui-button>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Attributes:**
|
|
54
|
+
- `variant` - Button style (`primary` | `secondary` | `ghost`)
|
|
55
|
+
- `size` - Button size (`sm` | `md` | `lg`)
|
|
56
|
+
- `disabled` - Disable the button
|
|
57
|
+
- `type` - Button type (`button` | `submit` | `reset`)
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 📅 Date Picker (`ui-date-picker`)
|
|
62
|
+
|
|
63
|
+
A customizable date picker with multiple format options and calendar support.
|
|
64
|
+
|
|
65
|
+
**Features:**
|
|
66
|
+
- 5 date formats: `YYYY-MM-DD`, `DD/MM/YYYY`, `MM/DD/YYYY`, `DD-MM-YYYY`, `MM-DD-YYYY`
|
|
67
|
+
- Native calendar picker integration
|
|
68
|
+
- Min/max date constraints
|
|
69
|
+
- Text input with format validation
|
|
70
|
+
- Real-time format conversion
|
|
71
|
+
- Disabled state support
|
|
72
|
+
- Custom events for date changes
|
|
73
|
+
|
|
74
|
+
**Usage:**
|
|
75
|
+
```html
|
|
76
|
+
<ui-date-picker
|
|
77
|
+
format="DD/MM/YYYY"
|
|
78
|
+
value="2026-02-26"
|
|
79
|
+
min="2026-01-01"
|
|
80
|
+
max="2026-12-31"
|
|
81
|
+
></ui-date-picker>
|
|
82
|
+
|
|
83
|
+
<script>
|
|
84
|
+
const picker = document.querySelector('ui-date-picker');
|
|
85
|
+
|
|
86
|
+
picker.addEventListener('date-change', (e) => {
|
|
87
|
+
console.log('ISO:', e.detail.value);
|
|
88
|
+
console.log('Formatted:', e.detail.formattedValue);
|
|
89
|
+
});
|
|
90
|
+
</script>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Attributes:**
|
|
94
|
+
- `format` - Date display format
|
|
95
|
+
- `value` - Date value in ISO format (YYYY-MM-DD)
|
|
96
|
+
- `min` - Minimum date (ISO format)
|
|
97
|
+
- `max` - Maximum date (ISO format)
|
|
98
|
+
- `disabled` - Disable the picker
|
|
99
|
+
- `placeholder` - Placeholder text
|
|
100
|
+
|
|
101
|
+
**Methods:**
|
|
102
|
+
- `getISOValue()` - Get date in ISO format
|
|
103
|
+
- `getFormattedValue()` - Get date in display format
|
|
104
|
+
- `setValue(isoDate)` - Set the date value
|
|
105
|
+
- `clear()` - Clear the date
|
|
106
|
+
|
|
107
|
+
**Events:**
|
|
108
|
+
- `date-change` - Fired when date changes
|
|
109
|
+
- `date-input` - Fired during input
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### 📋 Table (`ui-table`)
|
|
114
|
+
|
|
115
|
+
A dynamic data table with customizable columns and alignment.
|
|
116
|
+
|
|
117
|
+
**Features:**
|
|
118
|
+
- Dynamic column configuration
|
|
119
|
+
- Text alignment per column (left, center, right)
|
|
120
|
+
- Responsive layout
|
|
121
|
+
- Automatic row rendering
|
|
122
|
+
- Theme-aware styling
|
|
123
|
+
|
|
124
|
+
**Usage:**
|
|
125
|
+
```html
|
|
126
|
+
<ui-table id="myTable"></ui-table>
|
|
127
|
+
|
|
128
|
+
<script type="module">
|
|
129
|
+
const table = document.getElementById('myTable');
|
|
130
|
+
|
|
131
|
+
table.data = {
|
|
132
|
+
columns: [
|
|
133
|
+
{ key: 'name', label: 'Name' },
|
|
134
|
+
{ key: 'role', label: 'Role' },
|
|
135
|
+
{ key: 'score', label: 'Score', align: 'right' }
|
|
136
|
+
],
|
|
137
|
+
rows: [
|
|
138
|
+
{ name: 'Alice', role: 'Admin', score: 95 },
|
|
139
|
+
{ name: 'Bob', role: 'User', score: 87 }
|
|
140
|
+
]
|
|
141
|
+
};
|
|
142
|
+
</script>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Properties:**
|
|
146
|
+
- `data` - Object with `columns` and `rows`
|
|
147
|
+
- `columns`: Array of `{ key, label, align? }`
|
|
148
|
+
- `rows`: Array of objects matching column keys
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
### 📄 Pagination (`ui-pagination`)
|
|
153
|
+
|
|
154
|
+
Smart pagination component with ellipsis for large page counts.
|
|
155
|
+
|
|
156
|
+
**Features:**
|
|
157
|
+
- Automatic page number generation
|
|
158
|
+
- Smart ellipsis for large page counts
|
|
159
|
+
- Previous/Next navigation
|
|
160
|
+
- "Showing X to Y of Z" info display
|
|
161
|
+
- Disabled states for edge pages
|
|
162
|
+
- Custom events for page changes
|
|
163
|
+
- ARIA labels for accessibility
|
|
164
|
+
|
|
165
|
+
**Usage:**
|
|
166
|
+
```html
|
|
167
|
+
<ui-pagination
|
|
168
|
+
total="250"
|
|
169
|
+
current-page="5"
|
|
170
|
+
page-size="10"
|
|
171
|
+
></ui-pagination>
|
|
172
|
+
|
|
173
|
+
<script>
|
|
174
|
+
const pagination = document.querySelector('ui-pagination');
|
|
175
|
+
|
|
176
|
+
pagination.addEventListener('page-change', (e) => {
|
|
177
|
+
console.log('Page:', e.detail.page);
|
|
178
|
+
console.log('Total Pages:', e.detail.totalPages);
|
|
179
|
+
// Load new data...
|
|
180
|
+
});
|
|
181
|
+
</script>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Attributes/Properties:**
|
|
185
|
+
- `total` - Total number of items
|
|
186
|
+
- `current-page` - Current page number
|
|
187
|
+
- `page-size` - Items per page (default: 10)
|
|
188
|
+
|
|
189
|
+
**Computed Properties:**
|
|
190
|
+
- `totalPages` - Total number of pages
|
|
191
|
+
|
|
192
|
+
**Events:**
|
|
193
|
+
- `page-change` - Fired when page changes, includes pagination details
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 📝 Input (`ui-input`)
|
|
198
|
+
|
|
199
|
+
Advanced form input with built-in validation and error handling.
|
|
200
|
+
|
|
201
|
+
**Features:**
|
|
202
|
+
- Multiple input types: `text`, `email`, `password`, `number`, `tel`, `url`
|
|
203
|
+
- Built-in validation rules:
|
|
204
|
+
- Email domain validation
|
|
205
|
+
- Password matching
|
|
206
|
+
- Min/max length
|
|
207
|
+
- Regex patterns
|
|
208
|
+
- Custom validators
|
|
209
|
+
- Real-time validation feedback
|
|
210
|
+
- Error message display
|
|
211
|
+
- Touched state tracking
|
|
212
|
+
- Disabled state support
|
|
213
|
+
|
|
214
|
+
**Usage:**
|
|
215
|
+
```html
|
|
216
|
+
<ui-input
|
|
217
|
+
type="email"
|
|
218
|
+
label="Email"
|
|
219
|
+
placeholder="you@example.com"
|
|
220
|
+
required
|
|
221
|
+
validate="emailDomain:company.com"
|
|
222
|
+
></ui-input>
|
|
223
|
+
|
|
224
|
+
<ui-input
|
|
225
|
+
type="password"
|
|
226
|
+
label="Password"
|
|
227
|
+
minlength="8"
|
|
228
|
+
required
|
|
229
|
+
></ui-input>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Attributes:**
|
|
233
|
+
- `type` - Input type
|
|
234
|
+
- `label` - Label text
|
|
235
|
+
- `placeholder` - Placeholder text
|
|
236
|
+
- `required` - Required field
|
|
237
|
+
- `pattern` - Regex pattern
|
|
238
|
+
- `minlength` / `maxlength` - Length constraints
|
|
239
|
+
- `min` / `max` - Number constraints
|
|
240
|
+
- `error-message` - Custom error message
|
|
241
|
+
- `disabled` - Disable input
|
|
242
|
+
- `name` - Form field name
|
|
243
|
+
- `validate` - Validation rule (e.g., `emailDomain:company.com`)
|
|
244
|
+
|
|
245
|
+
**State:**
|
|
246
|
+
- `value` - Current input value
|
|
247
|
+
- `valid` - Validation state
|
|
248
|
+
- `touched` - Whether field has been interacted with
|
|
249
|
+
- `error` - Current error message
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### 🎯 Sidebar (`app-sidebar`)
|
|
254
|
+
|
|
255
|
+
Navigation sidebar component with links.
|
|
256
|
+
|
|
257
|
+
**Features:**
|
|
258
|
+
- Workspace navigation
|
|
259
|
+
- Active link highlighting (via routing)
|
|
260
|
+
- Theme-aware styling
|
|
261
|
+
|
|
262
|
+
**Usage:**
|
|
263
|
+
```html
|
|
264
|
+
<app-sidebar></app-sidebar>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
### 📐 Layout (`app-layout`)
|
|
270
|
+
|
|
271
|
+
Application layout wrapper with navigation and sidebar.
|
|
272
|
+
|
|
273
|
+
**Features:**
|
|
274
|
+
- Top navigation bar
|
|
275
|
+
- Sidebar integration
|
|
276
|
+
- Main content area with slot
|
|
277
|
+
- Responsive layout
|
|
278
|
+
|
|
279
|
+
**Usage:**
|
|
280
|
+
```html
|
|
281
|
+
<app-layout>
|
|
282
|
+
<your-page-component></your-page-component>
|
|
283
|
+
</app-layout>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Core Features
|
|
289
|
+
|
|
290
|
+
### Base Component
|
|
291
|
+
|
|
292
|
+
All components extend `BaseComponent` which provides:
|
|
293
|
+
|
|
294
|
+
**Signal-based Reactivity:**
|
|
295
|
+
```typescript
|
|
296
|
+
class MyComponent extends BaseComponent {
|
|
297
|
+
private count = this.useSignal(0);
|
|
298
|
+
|
|
299
|
+
connectedCallback() {
|
|
300
|
+
super.connectedCallback();
|
|
301
|
+
// count.set() automatically triggers re-render
|
|
302
|
+
this.count.set(this.count.get() + 1);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**State Management:**
|
|
308
|
+
```typescript
|
|
309
|
+
class MyComponent extends BaseComponent<{ user: string }> {
|
|
310
|
+
constructor() {
|
|
311
|
+
super();
|
|
312
|
+
this.state = { user: '' };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
updateUser() {
|
|
316
|
+
this.setState({ user: 'Alice' }); // Triggers re-render
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Router
|
|
322
|
+
|
|
323
|
+
Built-in client-side router with layouts:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
const routes = [
|
|
327
|
+
{
|
|
328
|
+
path: '/',
|
|
329
|
+
layout: 'app-layout',
|
|
330
|
+
load: () => import('./features/home/home-page'),
|
|
331
|
+
component: 'home-page'
|
|
332
|
+
}
|
|
333
|
+
];
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Store
|
|
337
|
+
|
|
338
|
+
Global state management:
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
import { store } from './core/store';
|
|
342
|
+
|
|
343
|
+
store.setState({ theme: 'dark' });
|
|
344
|
+
const currentState = store.getState();
|
|
345
|
+
|
|
346
|
+
store.subscribe(state => {
|
|
347
|
+
console.log('State changed:', state);
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Theming
|
|
354
|
+
|
|
355
|
+
All components use CSS custom properties for easy theming:
|
|
356
|
+
|
|
357
|
+
```css
|
|
358
|
+
:root {
|
|
359
|
+
--color-primary: #24ec71;
|
|
360
|
+
--color-primary-contrast: #ffffff;
|
|
361
|
+
--color-ink: #0f172a;
|
|
362
|
+
--color-muted: #f1f5f9;
|
|
363
|
+
--color-border: #e2e8f0;
|
|
364
|
+
--radius-md: 12px;
|
|
365
|
+
--radius-pill: 999px;
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Browser Support
|
|
372
|
+
|
|
373
|
+
- ✅ Chrome/Edge (latest)
|
|
374
|
+
- ✅ Firefox (latest)
|
|
375
|
+
- ✅ Safari (latest)
|
|
376
|
+
- ✅ All modern browsers with Custom Elements support
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Development
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# Install dependencies
|
|
384
|
+
npm install
|
|
385
|
+
|
|
386
|
+
# Start dev server
|
|
387
|
+
npm run dev
|
|
388
|
+
|
|
389
|
+
# Build library
|
|
390
|
+
npm run build:lib
|
|
391
|
+
|
|
392
|
+
# Build production app
|
|
393
|
+
npm run build:prod
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Project Structure
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
src/
|
|
402
|
+
├── core/
|
|
403
|
+
│ ├── base-component.ts # Base class with signals
|
|
404
|
+
│ ├── router.ts # Client-side routing
|
|
405
|
+
│ └── store.ts # Global state management
|
|
406
|
+
├── shared/
|
|
407
|
+
│ └── components/ # Reusable UI components
|
|
408
|
+
│ ├── button.ts
|
|
409
|
+
│ ├── date-picker.ts
|
|
410
|
+
│ ├── input.ts
|
|
411
|
+
│ ├── pagination.ts
|
|
412
|
+
│ └── table.ts
|
|
413
|
+
├── layouts/
|
|
414
|
+
│ └── app-layout.ts # Application shell
|
|
415
|
+
├── features/ # Page components
|
|
416
|
+
└── styles/
|
|
417
|
+
└── theme.css # Global theme variables
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Examples
|
|
423
|
+
|
|
424
|
+
### Form with Validation
|
|
425
|
+
|
|
426
|
+
```html
|
|
427
|
+
<form id="myForm">
|
|
428
|
+
<ui-input
|
|
429
|
+
type="email"
|
|
430
|
+
name="email"
|
|
431
|
+
label="Email"
|
|
432
|
+
required
|
|
433
|
+
></ui-input>
|
|
434
|
+
|
|
435
|
+
<ui-input
|
|
436
|
+
type="password"
|
|
437
|
+
name="password"
|
|
438
|
+
label="Password"
|
|
439
|
+
minlength="8"
|
|
440
|
+
required
|
|
441
|
+
></ui-input>
|
|
442
|
+
|
|
443
|
+
<ui-button type="submit">Submit</ui-button>
|
|
444
|
+
</form>
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Data Table with Pagination
|
|
448
|
+
|
|
449
|
+
```html
|
|
450
|
+
<ui-table id="dataTable"></ui-table>
|
|
451
|
+
<ui-pagination id="pagination" page-size="10"></ui-pagination>
|
|
452
|
+
|
|
453
|
+
<script type="module">
|
|
454
|
+
const table = document.getElementById('dataTable');
|
|
455
|
+
const pagination = document.getElementById('pagination');
|
|
456
|
+
|
|
457
|
+
async function loadData(page = 1) {
|
|
458
|
+
const response = await fetch(`/api/data?page=${page}`);
|
|
459
|
+
const data = await response.json();
|
|
460
|
+
|
|
461
|
+
table.data = {
|
|
462
|
+
columns: [
|
|
463
|
+
{ key: 'name', label: 'Name' },
|
|
464
|
+
{ key: 'email', label: 'Email' }
|
|
465
|
+
],
|
|
466
|
+
rows: data.items
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
pagination.total = data.total;
|
|
470
|
+
pagination.currentPage = page;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
pagination.addEventListener('page-change', (e) => {
|
|
474
|
+
loadData(e.detail.page);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
loadData(1);
|
|
478
|
+
</script>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Date Range Picker
|
|
482
|
+
|
|
483
|
+
```html
|
|
484
|
+
<ui-date-picker id="startDate" format="DD/MM/YYYY"></ui-date-picker>
|
|
485
|
+
<ui-date-picker id="endDate" format="DD/MM/YYYY"></ui-date-picker>
|
|
486
|
+
|
|
487
|
+
<script>
|
|
488
|
+
const start = document.getElementById('startDate');
|
|
489
|
+
const end = document.getElementById('endDate');
|
|
490
|
+
|
|
491
|
+
start.addEventListener('date-change', (e) => {
|
|
492
|
+
end.setAttribute('min', e.detail.value);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
end.addEventListener('date-change', (e) => {
|
|
496
|
+
start.setAttribute('max', e.detail.value);
|
|
497
|
+
});
|
|
498
|
+
</script>
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Contributing
|
|
504
|
+
|
|
505
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## License
|
|
510
|
+
|
|
511
|
+
MIT © [Your Name]
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## Links
|
|
516
|
+
|
|
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.2",
|
|
4
4
|
"description": "Lightweight web components library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/webcomponents.umd.js",
|
|
@@ -37,5 +37,10 @@
|
|
|
37
37
|
"ui-components",
|
|
38
38
|
"custom-elements"
|
|
39
39
|
],
|
|
40
|
-
"license": "MIT"
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"author": "Rodrigo Diniz",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/rodiniz/webcomponents"
|
|
45
|
+
}
|
|
41
46
|
}
|