@jpahd/kalendus
v0.9.4
Published
A sophisticated, responsive calendar web component built with Lit 3.x and TypeScript.
Downloads
954
Maintainers
Readme
kalendus
A sophisticated, responsive calendar web component built with Lit 3.x and TypeScript. Multiple view modes, overlapping event handling, per-instance localization, and 151 CSS design tokens.

Installation
npm install @jpahd/kalendusQuick Usage
<lms-calendar
.heading="My Calendar"
.activeDate=${{ day: 15, month: 3, year: 2024 }}
.entries=${myEvents}
.color="#1976d2"
></lms-calendar>Each instance auto-detects its locale from <html lang="...">. Override per-instance:
<lms-calendar locale="ja" .firstDayOfWeek="${0}"></lms-calendar>
<lms-calendar locale="es"></lms-calendar>
<lms-calendar locale="zh-Hans"></lms-calendar>Features
Multiple View Modes
- Month View: Traditional monthly calendar with color-coded event indicators
- Week View: 7-day view with hourly time slots, condensed windows (e.g., 3-day peeks) driven by CSS tokens, and pixel-perfect alignment
- Day View: Single-day view with detailed hourly scheduling
- Year View: 12 mini-month grids with density indicators (dot, heatmap, or count) and configurable drill targets for instant navigation
Advanced Event Handling
- Smart Overlapping: Cascading layout with progressive transparency preserves event visibility
- Duration-Based Positioning: Events positioned precisely by start time and duration via
LayoutCalculator - Multi-Day Events: Seamless spanning across multiple days with first/middle/last-day visual styling
- All-Day Events: Dedicated all-day section with row allocation via
allDayLayout - Responsive Density: Automatic layout optimization based on event count and viewport size
Modern Design
- Responsive Design: Mobile-first approach with adaptive layouts and container queries
- Color Dot Indicators: Scalable month view with color-coded event dots
- Accessibility: Full keyboard navigation, ARIA labels, focus trapping, and screen reader support
- CSS Custom Properties: 151 design tokens for comprehensive theming
Per-Instance Localization
- Independent Locale Per Instance: Multiple calendars on the same page can each display a different locale
- 28 Built-in Locales: See Supported Locales below for the full list
- Localized UI Strings: All buttons, labels, and messages translated per instance
- Localized Date Formatting: Weekday names, month names, and date formats use the instance's locale
- Configurable Week Start:
firstDayOfWeekproperty supports Monday (ISO), Sunday (US/JP), Saturday (AR), or any day
Properties
| Property | Type | Default | Description |
| ----------------- | ------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------- |
| heading | string | undefined | Calendar title displayed in header |
| activeDate | CalendarDate | Current date | Initially displayed date |
| entries | CalendarEntry[] | [] | Array of calendar events |
| color | string | '#000000' | Primary theme color (any CSS color format) |
| locale | string | document.documentElement.lang \|\| 'en' | Locale for UI strings and date formatting (auto-detected from page, overridable per-instance) |
| firstDayOfWeek | 0-6 | 1 | First day of the week (0=Sun, 1=Mon, ..., 6=Sat) |
| yearDrillTarget | 'day' \| 'month' | 'month' | Determines whether a year-view click opens day or month view |
| yearDensityMode | 'dot' \| 'heatmap' \| 'count' | 'dot' | Chooses how per-day entry density is visualized in year view |
| dir | 'ltr' \| 'rtl' \| 'auto' | 'auto' | Text direction; auto-detected from locale (RTL for ar, he, etc.) |
Event Structure
interface CalendarEntry {
heading: string;
content: string;
color: string; // any CSS color: hex, named, rgb(), hsl(), oklch(), …
isContinuation: boolean;
date: {
start: { day: number; month: number; year: number };
end: { day: number; month: number; year: number };
};
time: {
start: { hour: number; minute: number };
end: { hour: number; minute: number };
};
}Year View Controls
<lms-calendar
year-drill-target="day"
year-density-mode="heatmap"
.entries="${events}"
></lms-calendar>year-drill-target(day|month): picking a day can either open the specific day or simply focus its month.year-density-mode(dot|heatmap|count): swap between subtle dots, tonal heatmaps, or explicit counts for per-day density.
Supported Locales
| Code | Language | Default Week Start |
| --------- | ------------------ | ------------------ |
| en | English | Sunday |
| ar | Arabic | Saturday |
| bn | Bangla | Sunday |
| cs | Czech | Monday |
| da | Danish | Monday |
| de | German | Monday |
| de-DE | German (Germany) | Monday |
| el | Greek | Monday |
| es | Spanish | Monday |
| fi | Finnish | Monday |
| fr | French | Monday |
| he | Hebrew | Sunday |
| hi | Hindi | Sunday |
| id | Indonesian | Sunday |
| it | Italian | Monday |
| ja | Japanese | Sunday |
| ko | Korean | Sunday |
| nb | Norwegian Bokmål | Monday |
| nl | Dutch | Monday |
| pl | Polish | Monday |
| pt | Portuguese | Sunday |
| ru | Russian | Monday |
| sv | Swedish | Monday |
| th | Thai | Sunday |
| tr | Turkish | Monday |
| uk | Ukrainian | Monday |
| vi | Vietnamese | Monday |
| zh-Hans | Simplified Chinese | Sunday |
Styling & Theming
Kalendus ships unstyled by default (neutral base, respects OS light/dark mode). Import a built-in theme for an opinionated look:
import '@jpahd/kalendus/themes/default.css'; // polished light theme
import '@jpahd/kalendus/themes/ink.css'; // monochrome editorial
import '@jpahd/kalendus/themes/soft.css'; // pastel, generous radii
import '@jpahd/kalendus/themes/brutalist.css'; // bold borders, stark contrast
import '@jpahd/kalendus/themes/midnight.css'; // dark modeOverride individual CSS custom properties to fine-tune any theme:
lms-calendar {
--primary-color: #1976d2;
--background-color: #ffffff;
--entry-border-radius: 6px;
}See Theming Reference for all 5 built-in themes, color format support, and quick-start examples. For the complete token list, see the CSS Token Reference.
Documentation Map
| Audience | Document | Highlights | | ---------------------- | ------------------------------------------------------------ | -------------------------------------------------------- | | Integrators | Integration Guide | Framework recipes, theming tokens, analytics hooks | | Application Developers | Library Usage | API surface, data contracts, DOM events | | CSS / Design Systems | CSS Token Reference | Complete reference of all 151 CSS custom properties | | CSS / Design Systems | Theming Reference | Built-in themes, color formats, quick-start examples | | Events | Events Reference | All 8 custom events with payloads and code examples | | Layout | Layout & Positioning | Height requirements, responsive behavior, all-day events | | Troubleshooting | Troubleshooting | Top consumer issues and fixes | | Component Contributors | Developer Guide | Internal architecture, debugging tips, adding locales | | Rendering Internals | Rendering Calculations | Grid math, condensed weeks, density modes | | Architecture | Architecture Overview | Component tree, technologies, design patterns | | Design Tokens | Design Token Refactoring | Historical: token audit and proposed hierarchy | | Backend/API | API Server Guide | REST + SSE backend, database + adapters |
Testing
# Run unit tests
npm test
# Run tests in watch mode
npm run test:watch
# Run component tests (Web Test Runner + Playwright)
npm run test:components
# Run Storybook interaction tests (Vitest)
npm run test-storybookTest Categories
- Unit tests (
test/unit/lib/): Pure function tests with Mocha + Chai - Component tests (
test/unit/components/): Lit component tests with @open-wc/testing - Interaction tests: Storybook stories with
playfunctions, run via@storybook/addon-vitest
Storybook
Explore all features and variations in Storybook:
npm run storybookAvailable Stories
- Default: Basic calendar with sample events
- Theme stories: Default, Ink, Soft, Brutalist, Midnight — one story per built-in theme
- Custom Theming: Inline CSS variable overrides
- Locale stories: Individual stories for each supported locale (German, French, Spanish, Japanese, etc.)
- LocaleShowcase: 26 calendars on one page, each with a different locale
- WeekStartComparison: Side-by-side Monday-first vs Sunday-first
- Heavy Event Load: Stress testing with 200+ events
- Overlapping Events: Extreme overlap scenarios
- Tall Container: Verifies layout in oversized containers
- RTLShowcase: Side-by-side Arabic and Hebrew calendars with automatic RTL layout
- RTLOverride: Demonstrates explicit
dir="ltr"override on an RTL locale - Mobile View: Responsive mobile experience
Development
npm install
npm run storybook # Start Storybook dev server
npm run build # Build with Vite
npm test # Run tests
npm run lint # Run lit-analyzer + oxlint
npm run format # Format with oxfmt
npm run demo:gif # Record demo GIF (requires ffmpeg)See docs/developer-guide.md for internal architecture notes, troubleshooting checklists, and tips on extending condensed week layouts or localization.
API Server (optional)
The repository includes @jpahd/kalendus-server, a Hono + SQLite backend with REST/SSE endpoints.
# From the server directory
cd server
npm run db:migrate
npm run db:seed
npm run devConfiguration, endpoint overview, and adapter usage live in docs/api-server.md.
License
MIT License - see LICENSE file for details.
