# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Build and Development Commands ### TypeScript Build - **Build:** `npm run build` - Uses esbuild with NovaDI plugin to bundle to `wwwroot/js/calendar.js` - **Watch:** `npm run watch` - Auto-rebuild on file changes - **Clean:** `npm run clean` - Remove compiled output ### Testing - **Run tests:** `npm test` or `vitest` - Interactive watch mode - **Run once:** `npm run test:run` or `vitest run` - **Test UI:** `npm run test:ui` - Visual test interface - Tests use Vitest with jsdom environment (see `vitest.config.ts`) ### CSS Build - **Build CSS:** `npm run css:build` - PostCSS with nesting support - **Watch CSS:** `npm run css:watch` - Auto-rebuild CSS on changes - **Production CSS:** `npm run css:build:prod` - Minified with PurgeCSS - **Analyze CSS:** `npm run css:analyze` - CSS statistics and analysis ### Server - **Start:** `dotnet run` - ASP.NET Core Kestrel server on `http://localhost:8000` ## Architecture Overview ### Core Architectural Pattern This is a **manager-based, event-driven calendar application** using pure TypeScript with no UI frameworks. Communication happens exclusively through DOM CustomEvents via a central EventBus. **Key Principles:** - **No global state** - State lives in managers - **Event-driven** - All inter-component communication via CustomEvents (see `CoreEvents` constants) - **Dependency Injection** - Uses `@novadi/core` DI container - **Pure DOM** - No React/Vue/Angular, just vanilla TypeScript + DOM manipulation ### Dependency Injection Flow The application initializes in `src/index.ts` following this sequence: 1. **CalendarConfig.initialize()** - Static config from DOM attributes (``) 2. **Container setup** - Register all services, managers, renderers, utilities 3. **Manager initialization** - CalendarManager coordinates all other managers 4. **Deep linking** - Handle URL-based event navigation All dependencies are auto-wired using NovaDI's `@inject` decorators (configured in `build.js`). ### Event System **EventBus** (`src/core/EventBus.ts`) wraps DOM CustomEvents with debugging/logging: ```typescript // Emit eventBus.emit('view:changed', { view: 'week', date: new Date() }); // Listen eventBus.on('view:changed', (event: CustomEvent) => { const { view, date } = event.detail; }); ``` **Core events** are defined in `src/constants/CoreEvents.ts` (~20 essential events organized by category: lifecycle, view, navigation, data, grid, event management, system, filter, rendering). ### Manager Architecture Managers are the core organizational units. Each has a specific responsibility: **Primary Managers:** - `CalendarManager` - Main coordinator, initializes all managers - `ViewManager` - Handles view switching (day/week/month) - `NavigationManager` - Prev/next/today navigation, date changes - `EventManager` - Event CRUD operations, selection, lifecycle - `GridManager` - Calendar grid structure and layout - `HeaderManager` - Date headers and column rendering - `AllDayManager` - All-day event section management **Interaction Managers:** - `DragDropManager` - Event drag-and-drop functionality - `ResizeHandleManager` - Event resize handles - `DragHoverManager` - Visual feedback during drag operations - `EdgeScrollManager` - Auto-scroll when dragging near edges - `ScrollManager` - Grid scroll behavior **Support Managers:** - `ConfigManager` - Event-driven config updates (wraps CalendarConfig) and manages CSS custom properties - `EventLayoutCoordinator` - Coordinates event positioning - `EventStackManager` - Handles overlapping events - `EventFilterManager` - Filter events by criteria - `WorkHoursManager` - Work hours highlighting ### Renderer Architecture Renderers handle DOM creation and updates (separation of concerns from managers): - `EventRenderingService` - Main event rendering coordinator - `DateEventRenderer` / `AllDayEventRenderer` - Event DOM generation - `DateHeaderRenderer` - Date header rendering - `DateColumnRenderer` - Column structure - `GridRenderer` - Grid structure and time slots - `NavigationRenderer` - Navigation controls ### Core Services **CalendarConfig** (`src/core/CalendarConfig.ts`): - Static configuration class - Loads settings from DOM data attributes on `` element - Provides computed values (hourHeight, snapInterval, totalSlots, etc.) - ConfigManager wraps it for event-driven updates and automatically syncs CSS custom properties to the DOM **DateService** (`src/utils/DateService.ts`): - Uses `date-fns` and `date-fns-tz` for date calculations - Default timezone: `Europe/Copenhagen`, locale: `da-DK` **TimeFormatter** (`src/utils/TimeFormatter.ts`): - Consistent time/date formatting across the app - Configured via CalendarConfig **PositionUtils** (`src/utils/PositionUtils.ts`): - Convert between pixels and times - Snap-to-grid calculations **URLManager** (`src/utils/URLManager.ts`): - Deep linking to events - Parses `eventId` from URL ### Repository Pattern Event data is accessed through `IEventRepository` interface: - `MockEventRepository` - Current implementation using mock data from `wwwroot/data/mock-events.json` - Ready for API implementation swap ## Code Organization ``` src/ ├── constants/ # CoreEvents and other constants ├── core/ # EventBus, CalendarConfig (core infrastructure) ├── data/ # Data models and utilities ├── elements/ # Custom HTML elements (if any) ├── managers/ # Manager classes (business logic) ├── renderers/ # DOM rendering logic ├── repositories/ # Data access layer (IEventRepository, MockEventRepository) ├── types/ # TypeScript interfaces and types ├── utils/ # Utility functions (DateService, PositionUtils, etc.) └── index.ts # Application entry point and DI setup ``` ## Important Patterns ### Adding a New Manager 1. Create in `src/managers/YourManager.ts` 2. Use `@inject` for dependencies 3. Implement optional `initialize()` method if needed 4. Register in `src/index.ts` DI container 5. Listen to events via `eventBus.on()` (injected as `IEventBus`) 6. Emit events via `eventBus.emit()` ### Event Naming Convention Events follow `category:action` pattern: - `view:changed`, `view:rendered` - `nav:date-changed`, `nav:navigation-completed` - `data:loaded`, `data:error` - `event:created`, `event:updated`, `event:deleted` - `grid:rendered`, `grid:clicked` ### Grid Positioning Events are positioned using CSS Grid and absolute positioning: - Time slots are calculated via `CalendarConfig.slotHeight` and `minuteHeight` - `PositionUtils` handles pixel ↔ time conversions - Snap-to-grid uses `CalendarConfig.getGridSettings().snapInterval` ### Work Week Configuration CalendarConfig supports work week presets: - `standard` - Mon-Fri (default) - `compressed` - Mon-Thu - `midweek` - Wed-Fri - `weekend` - Sat-Sun - `fullweek` - Mon-Sun Change via `CalendarConfig.setWorkWeek('preset-id')` ## Testing Tests are written using Vitest with jsdom. Setup file: `test/setup.ts` Run individual test file: ```bash vitest run path/to/test-file.test.ts ``` ## CSS Architecture CSS is modular and built with PostCSS: - **Source:** `wwwroot/css/src/` (uses PostCSS nesting) - **Output:** `wwwroot/css/` - **Main file:** `calendar.css` (currently used) Planned modular CSS files: - `calendar-base-css.css` - Variables and base styles - `calendar-components-css.css` - UI components - `calendar-events-css.css` - Event styling - `calendar-layout-css.css` - Grid layout - `calendar-popup-css.css` - Modals and popups ## Debugging Enable EventBus debug mode (already enabled in `src/index.ts`): ```typescript eventBus.setDebug(true); ``` Access debug interface in browser console: ```javascript window.calendarDebug.eventBus.getEventLog(); // All events window.calendarDebug.eventManager; // Access EventManager window.calendarDebug.calendarManager; // Access CalendarManager ``` ## Configuration via HTML Set calendar options via data attributes on ``: ```html ```