npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ng-hub-ui-calendar

v19.0.1

Published

Calendar component for Angular applications with multiple views, native drag-and-drop, and event management

Readme

ng-hub-ui-calendar

npm version license

A powerful, flexible calendar component for Angular applications with multiple views, native drag-and-drop event rescheduling, custom templates, and full internationalization support.

🧩 Library Family ng-hub-ui

This library is part of the Hub UI ecosystem:

📑 Table of Contents

✨ Features

  • Multiple View Types: Month, Week, Day, and Year views
  • Native Drag & Drop: Reschedule events by dragging to different days
  • Custom Templates: Full control over event and day cell rendering
  • Internationalization: Built-in English and Spanish, extensible for any language
  • CSS Variables: Complete styling customization via CSS custom properties
  • TypeScript: Full type definitions with CalendarViewType enum
  • Standalone Components: Works with modern Angular's standalone architecture
  • Accessible: Keyboard navigation and ARIA support
  • Lightweight: No external dependencies (native HTML5 drag-and-drop)

📦 Installation

npm install ng-hub-ui-calendar ng-hub-ui-utils

🚀 Quick Start

import { Component, signal } from '@angular/core';
import { HubCalendarComponent, CalendarEvent, CalendarViewType } from 'ng-hub-ui-calendar';

@Component({
	selector: 'app-calendar-demo',
	standalone: true,
	imports: [HubCalendarComponent],
	template: `
		<hub-calendar [events]="events()" [view]="view()" (eventClick)="onEventClick($event)" (dayClick)="onDayClick($event)">
		</hub-calendar>
	`
})
export class CalendarDemoComponent {
	view = signal<CalendarViewType>(CalendarViewType.MONTH);

	events = signal<CalendarEvent[]>([
		{
			id: '1',
			title: 'Team Meeting',
			start: new Date(),
			end: new Date(Date.now() + 2 * 60 * 60 * 1000)
		}
	]);

	onEventClick(event: CalendarEvent): void {
		console.log('Event clicked:', event);
	}

	onDayClick(day: CalendarDay): void {
		console.log('Day clicked:', day);
	}
}

📚 Examples

Basic Calendar

import { HubCalendarComponent, CalendarEvent } from 'ng-hub-ui-calendar';

@Component({
	standalone: true,
	imports: [HubCalendarComponent],
	template: `<hub-calendar [events]="events()"></hub-calendar>`
})
export class BasicCalendarComponent {
	events = signal<CalendarEvent[]>([
		{ id: '1', title: 'Meeting', start: new Date() },
		{ id: '2', title: 'Lunch', start: new Date(), allDay: true }
	]);
}

View Types

import { CalendarViewType } from 'ng-hub-ui-calendar';

@Component({
	template: `
		<hub-calendar [events]="events()" [view]="currentView()" (viewChange)="currentView.set($event)"> </hub-calendar>

		<div class="controls">
			<button (click)="currentView.set(CalendarViewType.MONTH)">Month</button>
			<button (click)="currentView.set(CalendarViewType.WEEK)">Week</button>
			<button (click)="currentView.set(CalendarViewType.DAY)">Day</button>
			<button (click)="currentView.set(CalendarViewType.YEAR)">Year</button>
		</div>
	`
})
export class ViewTypesComponent {
	CalendarViewType = CalendarViewType;
	currentView = signal<CalendarViewType>(CalendarViewType.MONTH);
}

Custom Templates

import { HubCalendarComponent, EventTemplateDirective, DayCellTemplateDirective } from 'ng-hub-ui-calendar';

@Component({
	standalone: true,
	imports: [HubCalendarComponent, EventTemplateDirective, DayCellTemplateDirective],
	template: `
		<hub-calendar [events]="events()">
			<!-- Custom Event Template -->
			<ng-template eventTpt let-event="event">
				<div class="custom-event" [class.important]="event.data?.important">
					<span class="icon">{{ event.data?.important ? '⭐' : '📅' }}</span>
					<span>{{ event.title }}</span>
				</div>
			</ng-template>

			<!-- Custom Day Cell Template -->
			<ng-template dayCellTpt let-day="day">
				<div class="custom-day">
					<span class="day-number">{{ day.date | date : 'd' }}</span>
					@if (day.events.length > 0) {
					<span class="badge">{{ day.events.length }}</span>
					}
				</div>
			</ng-template>
		</hub-calendar>
	`
})
export class CustomTemplatesComponent {
	events = signal<CalendarEvent<{ important: boolean }>>([
		{ id: '1', title: 'VIP Meeting', start: new Date(), data: { important: true } },
		{ id: '2', title: 'Regular Task', start: new Date(), data: { important: false } }
	]);
}

Drag and Drop

@Component({
	template: `
		<hub-calendar [events]="events()" [config]="{ dragAndDropEnabled: true }" (eventDrop)="onEventDrop($event)">
		</hub-calendar>
	`
})
export class DragDropComponent {
	events = signal<CalendarEvent[]>([{ id: '1', title: 'Movable Event', start: new Date() }]);

	onEventDrop(event: { event: CalendarEvent; newDate: Date; previousDate: Date }): void {
		console.log(`Moved "${event.event.title}" from ${event.previousDate} to ${event.newDate}`);

		// Update the event in your data
		this.events.update((events) => events.map((e) => (e.id === event.event.id ? { ...e, start: event.newDate } : e)));
	}
}

Configuration

import { CalendarConfig, CalendarViewType } from 'ng-hub-ui-calendar';

@Component({
	template: ` <hub-calendar [events]="events()" [config]="calendarConfig" [weekStartsOn]="1"> </hub-calendar> `
})
export class ConfigurationComponent {
	calendarConfig: CalendarConfig = {
		initialView: CalendarViewType.WEEK,
		weekStartsOn: 1, // Monday
		showWeekNumbers: true,
		dayStartHour: 8,
		dayEndHour: 18,
		slotDuration: 30,
		availableViews: [CalendarViewType.MONTH, CalendarViewType.WEEK, CalendarViewType.DAY],
		dragAndDropEnabled: true,
		eventCreationEnabled: true
	};
}

Internationalization

// Using built-in translations
@Component({
	template: ` <hub-calendar [events]="events()" [locale]="'es'"> </hub-calendar> `
})
export class I18nComponent {}

// With HubTranslationService
// Add calendar translations to your i18n files:
// {
//   "calendar": {
//     "weekdays": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
//     "months": ["January", "February", ...],
//     "today": "Today",
//     "previous": "Previous",
//     "next": "Next"
//   }
// }

Event Handling

@Component({
	template: `
		<hub-calendar
			[events]="events()"
			[(view)]="currentView"
			[(selectedDate)]="selectedDate"
			(eventClick)="onEventClick($event)"
			(dayClick)="onDayClick($event)"
			(eventDrop)="onEventDrop($event)"
			(viewChange)="onViewChange($event)"
			(dateChange)="onDateChange($event)"
		>
		</hub-calendar>
	`
})
export class EventHandlingComponent {
	currentView = signal<CalendarViewType>(CalendarViewType.MONTH);
	selectedDate = signal<Date>(new Date());

	onEventClick(event: CalendarEvent): void {
		// Open event details modal
	}

	onDayClick(day: CalendarDay): void {
		// Create new event on this day
	}

	onEventDrop(data: { event: CalendarEvent; newDate: Date; previousDate: Date }): void {
		// Update event date in backend
	}

	onViewChange(view: CalendarViewType): void {
		// Track view analytics
	}

	onDateChange(date: Date): void {
		// Load events for new date range
	}
}

📖 API Reference

Inputs

| Input | Type | Default | Description | | -------------- | -------------------- | ------------ | ---------------------------------------- | | events | CalendarEvent[] | [] | Events to display on the calendar | | view | CalendarViewType | MONTH | Current view type (two-way bindable) | | selectedDate | Date | new Date() | Selected/focused date (two-way bindable) | | config | CalendarConfig | {} | Configuration options | | eventClass | string \| Function | - | CSS class(es) for events | | weekStartsOn | 0-6 | 0 | Day week starts on (0=Sunday) | | locale | string | 'en' | Language code for translations |

Outputs

| Output | Type | Description | | ------------ | ---------------------------------- | ---------------------------------------- | | eventClick | CalendarEvent | Emitted when an event is clicked | | dayClick | CalendarDay | Emitted when a day cell is clicked | | eventDrop | { event, newDate, previousDate } | Emitted when an event is dropped | | viewChange | CalendarViewType | Emitted when view type changes | | dateChange | Date | Emitted when navigation changes the date |

Interfaces

interface CalendarEvent<T = any> {
	id?: number | string;
	title: string;
	description?: string;
	start: Date;
	end?: Date;
	allDay?: boolean;
	cssClass?: string | ((event: CalendarEvent<T>) => string);
	data?: T;
}

interface CalendarDay<T = any> {
	date: Date;
	events: CalendarEvent<T>[];
	isToday: boolean;
	isCurrentMonth: boolean;
	isWeekend: boolean;
	isSelected?: boolean;
}

enum CalendarViewType {
	MONTH = 'month',
	WEEK = 'week',
	DAY = 'day',
	YEAR = 'year'
}

interface CalendarConfig {
	initialView?: CalendarViewType;
	weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
	showWeekNumbers?: boolean;
	dayStartHour?: number;
	dayEndHour?: number;
	slotDuration?: number;
	availableViews?: CalendarViewType[];
	dragAndDropEnabled?: boolean;
	eventCreationEnabled?: boolean;
}

🎨 Styling

CSS Variables

All styling can be customized via CSS variables:

hub-calendar {
	/* Container */
	--hub-calendar-bg: #ffffff;
	--hub-calendar-color: #1f2937;
	--hub-calendar-border-color: #e5e7eb;
	--hub-calendar-border-radius: 0.5rem;
	--hub-calendar-font-family: system-ui, -apple-system, sans-serif;

	/* Header */
	--hub-calendar-header-bg: #f9fafb;
	--hub-calendar-header-padding: 1rem;

	/* Buttons */
	--hub-calendar-btn-bg: #ffffff;
	--hub-calendar-btn-color: inherit;
	--hub-calendar-btn-border-color: #e5e7eb;
	--hub-calendar-btn-border-radius: 0.375rem;
	--hub-calendar-btn-hover-bg: #f3f4f6;
	--hub-calendar-btn-active-bg: #3b82f6;
	--hub-calendar-btn-active-color: #ffffff;

	/* Day cells */
	--hub-calendar-day-padding: 0.5rem;
	--hub-calendar-day-min-height: 80px;
	--hub-calendar-day-hover-bg: #f3f4f6;
	--hub-calendar-day-today-bg: #eff6ff;
	--hub-calendar-day-other-month-bg: #f9fafb;
	--hub-calendar-day-other-month-color: #9ca3af;
	--hub-calendar-day-weekend-bg: #fafafa;
	--hub-calendar-day-selected-bg: #dbeafe;
	--hub-calendar-day-drag-over-bg: #bfdbfe;

	/* Events */
	--hub-calendar-event-bg: #3b82f6;
	--hub-calendar-event-color: #ffffff;
	--hub-calendar-event-border-radius: 0.25rem;
	--hub-calendar-event-font-size: 0.75rem;

	/* Month cards (year view) */
	--hub-calendar-month-card-bg: #f9fafb;
	--hub-calendar-month-card-hover-bg: #f3f4f6;
	--hub-calendar-month-card-padding: 1.5rem;

	/* Colors */
	--hub-calendar-primary: #3b82f6;
	--hub-calendar-muted: #6b7280;
}

CSS Classes

| Class | Description | | --------------------------------- | -------------------------- | | .hub-calendar | Root container | | .hub-calendar__header | Top header with navigation | | .hub-calendar__day | Day cell container | | .hub-calendar__day--today | Today's date styling | | .hub-calendar__day--selected | Selected day styling | | .hub-calendar__day--weekend | Weekend day styling | | .hub-calendar__day--other-month | Days from adjacent months | | .hub-calendar__event | Event element | | .hub-calendar__month-card | Month card in year view |

📞 Support & License


Made with ❤️ by the Hub UI team