@nuvaprd/production-calendar
v1.2.1
Published
Web Component de calendario de producción compatible con Angular 8+
Downloads
1,058
Readme
📅 @nuvaprd/production-calendar
Web Component moderno para gestión de calendario de producción, construido con Lit y totalmente compatible con Angular 8+
✨ Características
- 🎯 Compatible con Angular 8+ - TypeScript 3.4+ soportado
- 🔄 Migración fácil desde angular-calendar - API similar
- 📱 3 Vistas: Mes, Semana, Día con navegación intuitiva
- 🎨 Colores personalizables por evento
- 📊 Panel lateral dinámico con vista Lista y Gantt
- ⏰ Control de visualización de horas - Ocultar/mostrar horas de eventos según necesidad
- 🚀 Rendimiento optimizado con Shadow DOM
- 🎭 Framework agnostic - Funciona con React, Vue, vanilla JS
- 🌍 i18n ready - Soporte multiidioma
- ♿ Accesible - ARIA labels y navegación por teclado
📦 Instalación
npm install @nuvaprd/production-calendar🚀 Integración con Angular 8+
1. Configurar el módulo
Agrega CUSTOM_ELEMENTS_SCHEMA en tu módulo para permitir Web Components:
// app-schedule.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@NgModule({
declarations: [ScheduleListComponent],
imports: [CommonModule, FormsModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA] // ← Importante para Web Components
})
export class AppScheduleModule { }2. Agregar script en angular.json
Agrega el archivo UMD en los scripts para carga global:
{
"architect": {
"build": {
"options": {
"scripts": [
"node_modules/@nuvaprd/production-calendar/dist/production-calendar.umd.js"
]
}
}
}
}3. Definir tipos en el componente
Dado que Angular 8 usa TypeScript 3.4 (sin soporte para import type), define los tipos localmente:
// schedule-list.component.ts
import { Component, OnInit } from '@angular/core';
// Tipos locales para compatibilidad con TS 3.4
type CalendarViewMode = 'month' | 'week' | 'day';
interface ProductionCalendarEvent {
id?: string | number;
title: string;
start: Date | string;
end?: Date | string;
color?: {
primary?: string;
secondary?: string;
};
meta?: any;
}
@Component({
selector: 'app-schedule-list',
templateUrl: './schedule-list.component.html'
})
export class ScheduleListComponent implements OnInit {
newCalendarView: CalendarViewMode = 'month';
newCalendarEvents: ProductionCalendarEvent[] = [];
viewDate: Date = new Date();
// ... resto del componente
}4. Usar en el template
<!-- schedule-list.component.html -->
<production-calendar
[attr.viewDate]="viewDate.toISOString()"
[attr.view]="newCalendarView"
(dayClick)="onDayClick($event)"
(eventClick)="onEventClick($event)">
</production-calendar>5. Manejar eventos
export class ScheduleListComponent {
// Sincronizar eventos al Web Component
syncEventsToNewCalendar() {
this.newCalendarEvents = this.events.map((event: any) => ({
id: event.id || 'evt-' + Math.random().toString(36).substr(2, 9),
title: event.title,
start: event.start,
end: event.end || event.start,
color: {
primary: (event.color && event.color.primary) || '#1e90ff',
secondary: (event.color && event.color.secondary) || '#D1E8FF'
},
meta: event // Guardar evento completo para recuperar después
}));
// Actualizar Web Component
setTimeout(() => {
const calendarElement: any = document.querySelector('production-calendar');
if (calendarElement) {
calendarElement.events = this.newCalendarEvents;
calendarElement.viewDate = this.viewDate;
calendarElement.view = this.newCalendarView;
}
}, 50);
}
// Manejar click en evento
onEventClick(event: any) {
const detail = event.detail;
const originalEvent = detail.event.meta; // Recuperar evento original
// ✨ Nuevo en v1.1.0: Usar la fecha clickeada en lugar de la fecha de inicio
const clickedDate = detail.clickedDate
? (typeof detail.clickedDate === 'string' ? new Date(detail.clickedDate) : detail.clickedDate)
: (typeof detail.event.start === 'string' ? new Date(detail.event.start) : detail.event.start);
// Abrir modal o realizar acción con la fecha exacta donde se hizo clic
this.openDialog(originalEvent, clickedDate);
}
// Manejar click en día
onDayClick(event: any) {
const detail = event.detail;
console.log('Día clickeado:', detail.date);
console.log('Eventos del día:', detail.events);
}
}📖 API Completa
Propiedades
| Propiedad | Tipo | Default | Descripción |
|-----------|------|---------|-------------|
| events | ProductionCalendarEvent[] | [] | Lista de eventos a mostrar |
| viewDate | Date \| string | new Date() | Fecha central del calendario |
| view | 'month' \| 'week' \| 'day' | 'month' | Vista actual del calendario |
| showEventTime | boolean \| string | false | Mostrar u ocultar la hora de los eventos |
Eventos Emitidos
| Evento | Tipo del Detail | Descripción |
|--------|-----------------|-------------|
| dayClick | { date: Date, events: ProductionCalendarEvent[] } | Se dispara al hacer clic en un día |
| eventClick | { event: ProductionCalendarEvent, clickedDate: Date, sourceEvent: Event } | Se dispara al hacer clic en un evento |
| viewChange | { view: CalendarViewMode } | Se dispara al cambiar la vista |
✨ Nuevo en v1.1.0: El evento
eventClickahora incluyeclickedDate, que representa la fecha de la celda del calendario donde se hizo clic. Esto es especialmente útil para eventos de múltiples días, dondeevent.startpuede ser diferente de la fecha clickeada.
Control de Visualización de Horas
Por defecto, las horas de los eventos no se muestran (showEventTime = false). Puedes controlar esto de dos formas:
Opción 1: Como atributo HTML
<production-calendar
[attr.showEventTime]="true"
[attr.viewDate]="viewDate.toISOString()"
[attr.view]="newCalendarView">
</production-calendar>Opción 2: Vía JavaScript/TypeScript
const calendarElement: any = document.querySelector('production-calendar');
calendarElement.showEventTime = true; // Mostrar horas
calendarElement.showEventTime = false; // Ocultar horas (default)Resultado:
showEventTime = false(default): "OP-2026-001 Ensamble Motores"showEventTime = true: "12:00 a.m. OP-2026-001 Ensamble Motores"
💡 Tip: Para eventos de producción, usualmente la hora exacta no es relevante, por eso está oculta por defecto. Actívala solo si tus eventos tienen horarios específicos importantes.
Tipo ProductionCalendarEvent
interface ProductionCalendarEvent {
id?: string | number; // ID único del evento
title: string; // Título a mostrar
start: Date | string; // Fecha/hora inicio (ISO string o Date)
end?: Date | string; // Fecha/hora fin (opcional)
color?: {
primary?: string; // Color principal (#hex)
secondary?: string; // Color secundario/fondo
};
meta?: Record<string, any>; // Metadatos personalizados
draggable?: boolean; // Si se puede arrastrar (futuro)
allDay?: boolean; // Si es evento de todo el día
}📅 Manejo de Eventos Multi-día
Cuando un evento tiene duración múltiple (ej: del 1 al 6 de marzo), aparece en varias celdas del calendario. Desde la v1.1.0, puedes obtener la fecha exacta donde el usuario hizo clic:
onEventClick(event: any) {
const detail = event.detail;
// Fecha de inicio del evento (siempre es la misma)
const eventStartDate = detail.event.start; // "2026-03-01"
// Fecha donde el usuario hizo clic (nueva en v1.1.0)
const clickedDate = detail.clickedDate; // "2026-03-04" si clickeó el día 4
// Ejemplo: Mostrar "Programación del 04/03/2026" en vez de "01/03/2026"
this.displayModal({
title: detail.event.title,
displayDate: clickedDate, // Usar fecha clickeada
eventData: detail.event.meta
});
}Beneficios:
- ✅ Mejor UX: muestra la fecha que el usuario realmente seleccionó
- ✅ Útil para modales de detalle o edición
- ✅ Compatible hacia atrás: usa
event.startsi no necesitas esta funcionalidad
🎨 Personalización
Usando CSS Variables
El calendario usa CSS Variables para fácil personalización:
production-calendar {
--calendar-bg: #ffffff;
--calendar-header-bg: #f8fafc;
--calendar-border: #e2e8f0;
--text-primary: #1f2937;
--text-secondary: #64748b;
--accent: #3b82f6;
--accent-light: #60a5fa;
}Z-index y Modales
El calendario usa z-index: 100-101 para el panel lateral. Los modales de Angular Material (z-index ~1000) quedarán correctamente por encima.
🔧 Troubleshooting
Error: "Declaration or statement expected"
Causa: Angular 8 usa TypeScript 3.4 que no soporta import type.
Solución: Define los tipos localmente en tu componente (ver sección de integración).
El modal de Angular queda detrás del panel
Causa: Conflicto de z-index.
Solución: Ya está resuelto en v1.0.2+. El calendario usa z-index bajo (100-101).
Eventos no se actualizan
Solución: Accede al elemento y actualiza la propiedad directamente:
const cal: any = document.querySelector('production-calendar');
cal.events = newEvents;
cal.viewDate = newDate;� Compatibilidad y Build
Soporte de ES2015 para Angular 8+
Desde v1.2.0, la librería se compila con target ES2015 para garantizar compatibilidad con:
- ✅ Angular 8+ (TypeScript 3.4+)
- ✅ Webpack 4.x con UglifyJS/Terser antiguo
- ✅ Navegadores desde IE11+ (con polyfills)
Problema Resuelto
Antes de v1.2.0:
ERROR in scripts.xxx.js from Terser
Unexpected token: punc (;) [scripts.xxx.js:3677,34]Causa: La librería usaba ES2022, que incluye operadores modernos (?., ??) no soportados por las versiones de Terser incluidas en Angular 8.
Uso recomendado:
- Angular 8-11: Usar UMD en
angular.jsonscripts - Angular 12+: Puede usar ESM directamente
�🛠️ Desarrollo Local
# Clonar e instalar
git clone <repo-url>
cd lib-wc-vite-lit-calendar
npm install
# Desarrollo
npm run dev
# Build para producción
npm run build
# Publicar
npm version patch
npm publish📜 Changelog
v1.2.1 (2026-04-09)
- ✨ Nueva propiedad
showEventTime: Control para mostrar/ocultar horas de eventos - 🎯 Default mejorado: Las horas ahora están ocultas por defecto (
showEventTime = false) - 💡 UX optimizada: Enfoque en eventos de producción donde la hora suele no ser relevante
- 📝 Documentación actualizada: Guía completa de uso de
showEventTime - ⚙️ Soporte para configuración vía atributo HTML o propiedad JavaScript
v1.2.0 (2026-04-09)
- 🔧 Compatibilidad mejorada con Angular 8+: Transpilación a ES2015 para evitar errores de Terser
- ✅ Resuelto error
Unexpected tokenen builds de producción (--prod) - 📦 Agregado
@types/nodepara soporte completo de TypeScript - ⚙️ Configuración de build optimizada (Vite + Terser ES2015)
- 🎯 Target ES2015 en tsconfig y vite.config para máxima compatibilidad
- 🛠️ Elimina errores de minificación en Angular 8 con webpack/uglify antiguos
Migración desde v1.1.x: No requiere cambios en tu código, solo actualiza:
npm update @nuvaprd/production-calendarv1.1.0 (2026-04-09)
- ✨ Nueva funcionalidad:
eventClickahora incluyeclickedDateen el detail - 🎯 Mejora para eventos multi-día: distingue entre fecha de inicio del evento y fecha donde se hizo clic
- 📝 Útil para modales que necesitan mostrar la fecha específica seleccionada por el usuario
- 🔄 Compatibilidad hacia atrás mantenida: el código existente sigue funcionando
v1.0.4 (2026-03-28)
- ✅ Ajuste en el contraste de las letras
v1.0.2 (2026-03-28)
- ✅ Ajustado z-index para compatibilidad con modales de Angular
- ✅ Cambiada fuente a Roboto para consistencia con aplicaciones Angular
- ✅ Mejorada sincronización de eventos con meta
v1.0.1 (2026-03-28)
- ✅ Corregida exportación de tipos para TypeScript 3.4
- ✅ Mejorada compatibilidad con Angular 8+
v1.0.0 (2026-03-27)
- 🎉 Lanzamiento inicial
- ✅ Vistas Mes, Semana, Día
- ✅ Panel lateral con Lista y Gantt
- ✅ API compatible con angular-calendar
📄 Licencia
MIT © [Nuvaprd]
Hecho con ❤️ usando Lit y Vite
# En el proyecto Angular de producción:
npm update @nuva/production-calendar
# O para forzar la última versión:
npm install @nuva/production-calendar@latest--
🎯 Migración desde angular-calendar
| angular-calendar | production-calendar |
|------------------|---------------------|
| mwl-calendar-month-view | production-calendar |
| [viewDate]="viewDate" | calendar.viewDate = viewDate |
| [events]="events" | calendar.events = events |
| (dayClicked)="fn($event)" | (dayClick)="fn($event)" |
| (eventClicked)="fn($event)" | (eventClick)="fn($event)" |
| CalendarEvent | ProductionCalendarEvent |
📋 Checklist de release
- [ ] Código probado con
npm run dev - [ ] Build sin errores:
npm run build - [ ] Versión actualizada:
npm version <tipo> - [ ] Publicado:
npm publish - [ ] Tag en git:
git push --tags
