ng-hub-ui-calendar 19.0.0

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 ADDED
@@ -0,0 +1,434 @@
1
+ # ng-hub-ui-calendar
2
+
3
+ [![npm version](https://img.shields.io/npm/v/ng-hub-ui-calendar.svg)](https://www.npmjs.com/package/ng-hub-ui-calendar)
4
+ [![license](https://img.shields.io/npm/l/ng-hub-ui-calendar.svg)](https://github.com/carlos-morcillo/ng-hub-ui-calendar/blob/main/LICENSE)
5
+
6
+ A powerful, flexible calendar component for Angular applications with multiple views, native drag-and-drop event rescheduling, custom templates, and full internationalization support.
7
+
8
+ ## 🧩 Library Family `ng-hub-ui`
9
+
10
+ This library is part of the **Hub UI** ecosystem:
11
+
12
+ - [**ng-hub-ui-accordion**](https://www.npmjs.com/package/ng-hub-ui-accordion)
13
+ - [**ng-hub-ui-action-sheet**](https://www.npmjs.com/package/ng-hub-ui-action-sheet)
14
+ - [**ng-hub-ui-avatar**](https://www.npmjs.com/package/ng-hub-ui-avatar)
15
+ - [**ng-hub-ui-board**](https://www.npmjs.com/package/ng-hub-ui-board)
16
+ - [**ng-hub-ui-breadcrumbs**](https://www.npmjs.com/package/ng-hub-ui-breadcrumbs)
17
+ - [**ng-hub-ui-calendar**](https://www.npmjs.com/package/ng-hub-ui-calendar) ← You are here
18
+ - [**ng-hub-ui-dropdown**](https://www.npmjs.com/package/ng-hub-ui-dropdown)
19
+ - [**ng-hub-ui-list**](https://www.npmjs.com/package/ng-hub-ui-list)
20
+ - [**ng-hub-ui-modal**](https://www.npmjs.com/package/ng-hub-ui-modal)
21
+ - [**ng-hub-ui-paginable**](https://www.npmjs.com/package/ng-hub-ui-paginable)
22
+ - [**ng-hub-ui-portal**](https://www.npmjs.com/package/ng-hub-ui-portal)
23
+ - [**ng-hub-ui-stepper**](https://www.npmjs.com/package/ng-hub-ui-stepper)
24
+ - [**ng-hub-ui-utils**](https://www.npmjs.com/package/ng-hub-ui-utils)
25
+
26
+ ## 📑 Table of Contents
27
+
28
+ - [Features](#-features)
29
+ - [Installation](#-installation)
30
+ - [Quick Start](#-quick-start)
31
+ - [Examples](#-examples)
32
+ - [Basic Calendar](#basic-calendar)
33
+ - [View Types](#view-types)
34
+ - [Custom Templates](#custom-templates)
35
+ - [Drag and Drop](#drag-and-drop)
36
+ - [Configuration](#configuration)
37
+ - [Internationalization](#internationalization)
38
+ - [Event Handling](#event-handling)
39
+ - [API Reference](#-api-reference)
40
+ - [Styling](#-styling)
41
+ - [Support & License](#-support--license)
42
+
43
+ ## ✨ Features
44
+
45
+ - **Multiple View Types**: Month, Week, Day, and Year views
46
+ - **Native Drag & Drop**: Reschedule events by dragging to different days
47
+ - **Custom Templates**: Full control over event and day cell rendering
48
+ - **Internationalization**: Built-in English and Spanish, extensible for any language
49
+ - **CSS Variables**: Complete styling customization via CSS custom properties
50
+ - **TypeScript**: Full type definitions with CalendarViewType enum
51
+ - **Standalone Components**: Works with modern Angular's standalone architecture
52
+ - **Accessible**: Keyboard navigation and ARIA support
53
+ - **Lightweight**: No external dependencies (native HTML5 drag-and-drop)
54
+
55
+ ## 📦 Installation
56
+
57
+ ```bash
58
+ npm install ng-hub-ui-calendar ng-hub-ui-utils
59
+ ```
60
+
61
+ ## 🚀 Quick Start
62
+
63
+ ```typescript
64
+ import { Component, signal } from '@angular/core';
65
+ import { HubCalendarComponent, CalendarEvent, CalendarViewType } from 'ng-hub-ui-calendar';
66
+
67
+ @Component({
68
+ selector: 'app-calendar-demo',
69
+ standalone: true,
70
+ imports: [HubCalendarComponent],
71
+ template: `
72
+ <hub-calendar [events]="events()" [view]="view()" (eventClick)="onEventClick($event)" (dayClick)="onDayClick($event)">
73
+ </hub-calendar>
74
+ `
75
+ })
76
+ export class CalendarDemoComponent {
77
+ view = signal<CalendarViewType>(CalendarViewType.MONTH);
78
+
79
+ events = signal<CalendarEvent[]>([
80
+ {
81
+ id: '1',
82
+ title: 'Team Meeting',
83
+ start: new Date(),
84
+ end: new Date(Date.now() + 2 * 60 * 60 * 1000)
85
+ }
86
+ ]);
87
+
88
+ onEventClick(event: CalendarEvent): void {
89
+ console.log('Event clicked:', event);
90
+ }
91
+
92
+ onDayClick(day: CalendarDay): void {
93
+ console.log('Day clicked:', day);
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## 📚 Examples
99
+
100
+ ### Basic Calendar
101
+
102
+ ```typescript
103
+ import { HubCalendarComponent, CalendarEvent } from 'ng-hub-ui-calendar';
104
+
105
+ @Component({
106
+ standalone: true,
107
+ imports: [HubCalendarComponent],
108
+ template: `<hub-calendar [events]="events()"></hub-calendar>`
109
+ })
110
+ export class BasicCalendarComponent {
111
+ events = signal<CalendarEvent[]>([
112
+ { id: '1', title: 'Meeting', start: new Date() },
113
+ { id: '2', title: 'Lunch', start: new Date(), allDay: true }
114
+ ]);
115
+ }
116
+ ```
117
+
118
+ ### View Types
119
+
120
+ ```typescript
121
+ import { CalendarViewType } from 'ng-hub-ui-calendar';
122
+
123
+ @Component({
124
+ template: `
125
+ <hub-calendar [events]="events()" [view]="currentView()" (viewChange)="currentView.set($event)"> </hub-calendar>
126
+
127
+ <div class="controls">
128
+ <button (click)="currentView.set(CalendarViewType.MONTH)">Month</button>
129
+ <button (click)="currentView.set(CalendarViewType.WEEK)">Week</button>
130
+ <button (click)="currentView.set(CalendarViewType.DAY)">Day</button>
131
+ <button (click)="currentView.set(CalendarViewType.YEAR)">Year</button>
132
+ </div>
133
+ `
134
+ })
135
+ export class ViewTypesComponent {
136
+ CalendarViewType = CalendarViewType;
137
+ currentView = signal<CalendarViewType>(CalendarViewType.MONTH);
138
+ }
139
+ ```
140
+
141
+ ### Custom Templates
142
+
143
+ ```typescript
144
+ import { HubCalendarComponent, EventTemplateDirective, DayCellTemplateDirective } from 'ng-hub-ui-calendar';
145
+
146
+ @Component({
147
+ standalone: true,
148
+ imports: [HubCalendarComponent, EventTemplateDirective, DayCellTemplateDirective],
149
+ template: `
150
+ <hub-calendar [events]="events()">
151
+ <!-- Custom Event Template -->
152
+ <ng-template eventTpt let-event="event">
153
+ <div class="custom-event" [class.important]="event.data?.important">
154
+ <span class="icon">{{ event.data?.important ? '⭐' : '📅' }}</span>
155
+ <span>{{ event.title }}</span>
156
+ </div>
157
+ </ng-template>
158
+
159
+ <!-- Custom Day Cell Template -->
160
+ <ng-template dayCellTpt let-day="day">
161
+ <div class="custom-day">
162
+ <span class="day-number">{{ day.date | date : 'd' }}</span>
163
+ @if (day.events.length > 0) {
164
+ <span class="badge">{{ day.events.length }}</span>
165
+ }
166
+ </div>
167
+ </ng-template>
168
+ </hub-calendar>
169
+ `
170
+ })
171
+ export class CustomTemplatesComponent {
172
+ events = signal<CalendarEvent<{ important: boolean }>>([
173
+ { id: '1', title: 'VIP Meeting', start: new Date(), data: { important: true } },
174
+ { id: '2', title: 'Regular Task', start: new Date(), data: { important: false } }
175
+ ]);
176
+ }
177
+ ```
178
+
179
+ ### Drag and Drop
180
+
181
+ ```typescript
182
+ @Component({
183
+ template: `
184
+ <hub-calendar [events]="events()" [config]="{ dragAndDropEnabled: true }" (eventDrop)="onEventDrop($event)">
185
+ </hub-calendar>
186
+ `
187
+ })
188
+ export class DragDropComponent {
189
+ events = signal<CalendarEvent[]>([{ id: '1', title: 'Movable Event', start: new Date() }]);
190
+
191
+ onEventDrop(event: { event: CalendarEvent; newDate: Date; previousDate: Date }): void {
192
+ console.log(`Moved "${event.event.title}" from ${event.previousDate} to ${event.newDate}`);
193
+
194
+ // Update the event in your data
195
+ this.events.update((events) => events.map((e) => (e.id === event.event.id ? { ...e, start: event.newDate } : e)));
196
+ }
197
+ }
198
+ ```
199
+
200
+ ### Configuration
201
+
202
+ ```typescript
203
+ import { CalendarConfig, CalendarViewType } from 'ng-hub-ui-calendar';
204
+
205
+ @Component({
206
+ template: ` <hub-calendar [events]="events()" [config]="calendarConfig" [weekStartsOn]="1"> </hub-calendar> `
207
+ })
208
+ export class ConfigurationComponent {
209
+ calendarConfig: CalendarConfig = {
210
+ initialView: CalendarViewType.WEEK,
211
+ weekStartsOn: 1, // Monday
212
+ showWeekNumbers: true,
213
+ dayStartHour: 8,
214
+ dayEndHour: 18,
215
+ slotDuration: 30,
216
+ availableViews: [CalendarViewType.MONTH, CalendarViewType.WEEK, CalendarViewType.DAY],
217
+ dragAndDropEnabled: true,
218
+ eventCreationEnabled: true
219
+ };
220
+ }
221
+ ```
222
+
223
+ ### Internationalization
224
+
225
+ ```typescript
226
+ // Using built-in translations
227
+ @Component({
228
+ template: ` <hub-calendar [events]="events()" [locale]="'es'"> </hub-calendar> `
229
+ })
230
+ export class I18nComponent {}
231
+
232
+ // With HubTranslationService
233
+ // Add calendar translations to your i18n files:
234
+ // {
235
+ // "calendar": {
236
+ // "weekdays": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
237
+ // "months": ["January", "February", ...],
238
+ // "today": "Today",
239
+ // "previous": "Previous",
240
+ // "next": "Next"
241
+ // }
242
+ // }
243
+ ```
244
+
245
+ ### Event Handling
246
+
247
+ ```typescript
248
+ @Component({
249
+ template: `
250
+ <hub-calendar
251
+ [events]="events()"
252
+ [(view)]="currentView"
253
+ [(selectedDate)]="selectedDate"
254
+ (eventClick)="onEventClick($event)"
255
+ (dayClick)="onDayClick($event)"
256
+ (eventDrop)="onEventDrop($event)"
257
+ (viewChange)="onViewChange($event)"
258
+ (dateChange)="onDateChange($event)"
259
+ >
260
+ </hub-calendar>
261
+ `
262
+ })
263
+ export class EventHandlingComponent {
264
+ currentView = signal<CalendarViewType>(CalendarViewType.MONTH);
265
+ selectedDate = signal<Date>(new Date());
266
+
267
+ onEventClick(event: CalendarEvent): void {
268
+ // Open event details modal
269
+ }
270
+
271
+ onDayClick(day: CalendarDay): void {
272
+ // Create new event on this day
273
+ }
274
+
275
+ onEventDrop(data: { event: CalendarEvent; newDate: Date; previousDate: Date }): void {
276
+ // Update event date in backend
277
+ }
278
+
279
+ onViewChange(view: CalendarViewType): void {
280
+ // Track view analytics
281
+ }
282
+
283
+ onDateChange(date: Date): void {
284
+ // Load events for new date range
285
+ }
286
+ }
287
+ ```
288
+
289
+ ## 📖 API Reference
290
+
291
+ ### Inputs
292
+
293
+ | Input | Type | Default | Description |
294
+ | -------------- | -------------------- | ------------ | ---------------------------------------- |
295
+ | `events` | `CalendarEvent[]` | `[]` | Events to display on the calendar |
296
+ | `view` | `CalendarViewType` | `MONTH` | Current view type (two-way bindable) |
297
+ | `selectedDate` | `Date` | `new Date()` | Selected/focused date (two-way bindable) |
298
+ | `config` | `CalendarConfig` | `{}` | Configuration options |
299
+ | `eventClass` | `string \| Function` | - | CSS class(es) for events |
300
+ | `weekStartsOn` | `0-6` | `0` | Day week starts on (0=Sunday) |
301
+ | `locale` | `string` | `'en'` | Language code for translations |
302
+
303
+ ### Outputs
304
+
305
+ | Output | Type | Description |
306
+ | ------------ | ---------------------------------- | ---------------------------------------- |
307
+ | `eventClick` | `CalendarEvent` | Emitted when an event is clicked |
308
+ | `dayClick` | `CalendarDay` | Emitted when a day cell is clicked |
309
+ | `eventDrop` | `{ event, newDate, previousDate }` | Emitted when an event is dropped |
310
+ | `viewChange` | `CalendarViewType` | Emitted when view type changes |
311
+ | `dateChange` | `Date` | Emitted when navigation changes the date |
312
+
313
+ ### Interfaces
314
+
315
+ ```typescript
316
+ interface CalendarEvent<T = any> {
317
+ id?: number | string;
318
+ title: string;
319
+ description?: string;
320
+ start: Date;
321
+ end?: Date;
322
+ allDay?: boolean;
323
+ cssClass?: string | ((event: CalendarEvent<T>) => string);
324
+ data?: T;
325
+ }
326
+
327
+ interface CalendarDay<T = any> {
328
+ date: Date;
329
+ events: CalendarEvent<T>[];
330
+ isToday: boolean;
331
+ isCurrentMonth: boolean;
332
+ isWeekend: boolean;
333
+ isSelected?: boolean;
334
+ }
335
+
336
+ enum CalendarViewType {
337
+ MONTH = 'month',
338
+ WEEK = 'week',
339
+ DAY = 'day',
340
+ YEAR = 'year'
341
+ }
342
+
343
+ interface CalendarConfig {
344
+ initialView?: CalendarViewType;
345
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
346
+ showWeekNumbers?: boolean;
347
+ dayStartHour?: number;
348
+ dayEndHour?: number;
349
+ slotDuration?: number;
350
+ availableViews?: CalendarViewType[];
351
+ dragAndDropEnabled?: boolean;
352
+ eventCreationEnabled?: boolean;
353
+ }
354
+ ```
355
+
356
+ ## 🎨 Styling
357
+
358
+ ### CSS Variables
359
+
360
+ All styling can be customized via CSS variables:
361
+
362
+ ```css
363
+ hub-calendar {
364
+ /* Container */
365
+ --hub-calendar-bg: #ffffff;
366
+ --hub-calendar-color: #1f2937;
367
+ --hub-calendar-border-color: #e5e7eb;
368
+ --hub-calendar-border-radius: 0.5rem;
369
+ --hub-calendar-font-family: system-ui, -apple-system, sans-serif;
370
+
371
+ /* Header */
372
+ --hub-calendar-header-bg: #f9fafb;
373
+ --hub-calendar-header-padding: 1rem;
374
+
375
+ /* Buttons */
376
+ --hub-calendar-btn-bg: #ffffff;
377
+ --hub-calendar-btn-color: inherit;
378
+ --hub-calendar-btn-border-color: #e5e7eb;
379
+ --hub-calendar-btn-border-radius: 0.375rem;
380
+ --hub-calendar-btn-hover-bg: #f3f4f6;
381
+ --hub-calendar-btn-active-bg: #3b82f6;
382
+ --hub-calendar-btn-active-color: #ffffff;
383
+
384
+ /* Day cells */
385
+ --hub-calendar-day-padding: 0.5rem;
386
+ --hub-calendar-day-min-height: 80px;
387
+ --hub-calendar-day-hover-bg: #f3f4f6;
388
+ --hub-calendar-day-today-bg: #eff6ff;
389
+ --hub-calendar-day-other-month-bg: #f9fafb;
390
+ --hub-calendar-day-other-month-color: #9ca3af;
391
+ --hub-calendar-day-weekend-bg: #fafafa;
392
+ --hub-calendar-day-selected-bg: #dbeafe;
393
+ --hub-calendar-day-drag-over-bg: #bfdbfe;
394
+
395
+ /* Events */
396
+ --hub-calendar-event-bg: #3b82f6;
397
+ --hub-calendar-event-color: #ffffff;
398
+ --hub-calendar-event-border-radius: 0.25rem;
399
+ --hub-calendar-event-font-size: 0.75rem;
400
+
401
+ /* Month cards (year view) */
402
+ --hub-calendar-month-card-bg: #f9fafb;
403
+ --hub-calendar-month-card-hover-bg: #f3f4f6;
404
+ --hub-calendar-month-card-padding: 1.5rem;
405
+
406
+ /* Colors */
407
+ --hub-calendar-primary: #3b82f6;
408
+ --hub-calendar-muted: #6b7280;
409
+ }
410
+ ```
411
+
412
+ ### CSS Classes
413
+
414
+ | Class | Description |
415
+ | --------------------------------- | -------------------------- |
416
+ | `.hub-calendar` | Root container |
417
+ | `.hub-calendar__header` | Top header with navigation |
418
+ | `.hub-calendar__day` | Day cell container |
419
+ | `.hub-calendar__day--today` | Today's date styling |
420
+ | `.hub-calendar__day--selected` | Selected day styling |
421
+ | `.hub-calendar__day--weekend` | Weekend day styling |
422
+ | `.hub-calendar__day--other-month` | Days from adjacent months |
423
+ | `.hub-calendar__event` | Event element |
424
+ | `.hub-calendar__month-card` | Month card in year view |
425
+
426
+ ## 📞 Support & License
427
+
428
+ - **Issues**: [GitHub Issues](https://github.com/carlos-morcillo/ng-hub-ui-calendar/issues)
429
+ - **Author**: Carlos Morcillo
430
+ - **License**: MIT
431
+
432
+ ---
433
+
434
+ Made with ❤️ by the Hub UI team