whensday-calendar-lib
Version:
A flexible calendar library with Whensday/Gregorian calendar systems, event management, and customizable UI components
368 lines (305 loc) • 9.93 kB
Markdown
A flexible React calendar library with support for both Whensday and Gregorian calendar systems, featuring event management, schedule tracking, and customizable UI components.
- **Dual Calendar Systems**: Switch between Whensday and Gregorian calendars
- **Multiple Views**: Month, Week, and Day views
- **Event Management**: Add, edit, move, and delete events with drag-and-drop support
- **Schedule Management**: Create recurring schedules with on/off patterns
- **Holiday Booking**: Built-in holiday tracking and booking system
- **Layer Organization**: Organize events and schedules into color-coded layers
- **Customizable Themes**: Fully customizable styling with CSS variables
- **TypeScript Support**: Full TypeScript definitions included
```bash
npm install whensday-calendar-lib
```
```tsx
import React from 'react';
import { Calendar } from '@whensday/calendar-lib';
function App() {
const [events, setEvents] = React.useState([]);
const [layers, setLayers] = React.useState([]);
const [schedules, setSchedules] = React.useState([]);
const handleEventClick = (event) => {
console.log('Event clicked:', event);
};
const handleEventAdd = (date, time) => {
console.log('Add event on:', date, 'at:', time);
};
return (
<Calendar
events={events}
layers={layers}
schedules={schedules}
onEventClick={handleEventClick}
onEventAdd={handleEventAdd}
theme={{
colors: {
primary: '#3b82f6',
accent: '#f59e0b',
background: '#111827',
surface: '#1f2937',
text: '#f9fafb',
}
}}
/>
);
}
```
The main `Calendar` component accepts the following props:
- `events?: Event[]` - Array of calendar events
- `layers?: Layer[]` - Array of organizational layers
- `schedules?: Schedule[]` - Array of recurring schedules
- `view?: CalendarView` - Current view ('month' | 'week' | 'day')
- `system?: CalendarSystem` - Calendar system ('whensday' | 'gregorian')
- `displayDate?: DayInGrid` - Currently displayed date
#### Event Handlers
- `onEventClick?: (event: Event) => void` - Called when an event is clicked
- `onEventAdd?: (date: DayInGrid, time?: string) => void` - Called when adding a new event
- `onEventUpdate?: (event: Event) => void` - Called when an event is updated
- `onEventDelete?: (eventId: string) => void` - Called when an event is deleted
- `onEventMove?: (eventId: string, newDayTimestamp: number, newStartTime?: string) => void` - Called when an event is moved
- `onDateClick?: (date: DayInGrid) => void` - Called when a date is clicked
- `onViewChange?: (view: CalendarView) => void` - Called when the view changes
- `onSystemChange?: (system: CalendarSystem) => void` - Called when the calendar system changes
- `theme?: Partial<CalendarTheme>` - Custom theme configuration
- `className?: string` - Additional CSS classes
- `style?: React.CSSProperties` - Additional inline styles
- `enableDragAndDrop?: boolean` - Enable drag-and-drop functionality (default: true)
- `enableScheduleManagement?: boolean` - Enable schedule features (default: true)
- `enableHolidayBooking?: boolean` - Enable holiday booking (default: true)
- `enableTravelTime?: boolean` - Enable travel time calculations (default: true)
- `enableRecurringEvents?: boolean` - Enable recurring events (default: true)
#### Display Options
- `showWeekNumbers?: boolean` - Show week numbers (default: false)
- `showTodayIndicator?: boolean` - Show today indicator (default: true)
- `showHolidayIndicators?: boolean` - Show holiday indicators (default: true)
- `showScheduleIndicators?: boolean` - Show schedule indicators (default: true)
### Types
#### Event
```typescript
interface Event {
id: string;
name: string;
layerId: string | null;
color?: string;
startDate: number; // UTC timestamp
endDate?: number; // UTC timestamp
eventType: 'event' | 'deadline' | 'task' | 'birthday';
isAllDay: boolean;
location?: LocationDetails | null;
startLocation?: LocationDetails | null;
endLocation?: LocationDetails | null;
isCompleted?: boolean;
tags?: string[];
startTime?: string; // "HH:MM" format
endTime?: string; // "HH:MM" format
travelTimeBefore?: number; // minutes
travelTimeAfter?: number; // minutes
doByDate?: number; // UTC timestamp
doByTime?: string; // "HH:MM" format
dueTime?: string; // "HH:MM" format
duePeriod?: 'morning' | 'afternoon' | 'evening';
isRecurring?: boolean;
naturalLanguageRule?: string;
recurrenceRule?: string;
}
```
```typescript
interface Layer {
id: string;
name: string;
color: string; // Hex color
isVisible: boolean;
parentId?: string;
}
```
```typescript
interface Schedule {
id: string;
name: string;
layerId: string | null;
color: string | null;
startDate: number; // UTC timestamp
endDate?: number; // UTC timestamp
pattern: {
on: number;
off: number;
};
isVisible: boolean;
initialHolidayBalance?: number;
bookedHolidays?: number[]; // UTC timestamps
completedDays?: number[]; // UTC timestamps
holidaySettings?: HolidaySettings;
exemptions?: ScheduleExemption[];
bonusDays?: number[]; // UTC timestamps
}
```
The library provides several utility functions for working with dates:
```typescript
import {
gregorianToWhensday,
whensdayToGregorian,
dayInGridToDate,
areUniversalDaysEqual,
formatUniversalDate,
} from '@whensday/calendar-lib';
// Convert between calendar systems
const whensdayDate = gregorianToWhensday(new Date());
const gregorianDate = whensdayToGregorian(whensdayDate);
// Work with universal dates
const dayInGrid = { year: 2024, month: 0, day: 1, monthName: 'January' };
const date = dayInGridToDate(dayInGrid, 'gregorian');
const formatted = formatUniversalDate(date.getTime(), 'gregorian');
```
A custom hook for managing calendar state:
```typescript
import { useCalendar } from '@whensday/calendar-lib';
const {
view,
system,
displayDate,
calendarGrid,
currentMonthName,
currentYear,
goToNextPeriod,
goToPrevPeriod,
goToToday,
goToDate,
toggleSystem,
useScheduleCalculations,
} = useCalendar('month', 'gregorian');
```
The library uses CSS variables for theming. You can customize the appearance by overriding these variables:
```css
.whensday-calendar {
--calendar-primary:
--calendar-secondary:
--calendar-accent:
--calendar-background:
--calendar-surface:
--calendar-text:
--calendar-text-secondary:
--calendar-border:
--calendar-today:
--calendar-whensday-leap:
--calendar-font-primary: 'Inter, system-ui, sans-serif';
--calendar-font-secondary: 'Bangers, cursive';
--calendar-spacing-xs: 0.25rem;
--calendar-spacing-sm: 0.5rem;
--calendar-spacing-md: 1rem;
--calendar-spacing-lg: 1.5rem;
--calendar-spacing-xl: 2rem;
--calendar-border-radius-sm: 0.25rem;
--calendar-border-radius-md: 0.5rem;
--calendar-border-radius-lg: 0.75rem;
}
```
The Whensday calendar is an alternative calendar system with the following characteristics:
- **13 months**: 12 regular months of 28 days each, plus a 13th month (Sol) of 14-15 days
- **Leap day**: The 15th day of Sol month in leap years is called "Whensday"
- **Year start**: The Whensday year begins on March 1st of the Gregorian calendar
- **Consistent weeks**: Each month starts on the same day of the week
## Examples
### Basic Calendar
```tsx
<Calendar
events={[
{
id: '1',
name: 'Team Meeting',
layerId: 'work',
startDate: new Date('2024-01-15T10:00:00Z').getTime(),
endDate: new Date('2024-01-15T11:00:00Z').getTime(),
eventType: 'event',
isAllDay: false,
startTime: '10:00',
endTime: '11:00',
}
]}
layers={[
{
id: 'work',
name: 'Work',
color: '#3b82f6',
isVisible: true,
}
]}
onEventClick={(event) => console.log('Event clicked:', event)}
/>
```
```tsx
<Calendar
theme={{
colors: {
primary: '#8b5cf6',
accent: '#f59e0b',
background: '#0f172a',
surface: '#1e293b',
text: '#f8fafc',
textSecondary: '#cbd5e1',
border: '#334155',
today: '#f59e0b',
whensdayLeap: '#ec4899',
},
fonts: {
primary: 'Inter, system-ui, sans-serif',
secondary: 'Bangers, cursive',
},
spacing: {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
},
borderRadius: {
sm: '0.25rem',
md: '0.5rem',
lg: '0.75rem',
},
}}
/>
```
```tsx
<Calendar
schedules={[
{
id: 'work-schedule',
name: 'Work Schedule',
layerId: 'work',
startDate: new Date('2024-01-01T00:00:00Z').getTime(),
pattern: { on: 5, off: 2 }, // 5 days on, 2 days off
isVisible: true,
holidaySettings: {
enabled: true,
onDays: 5,
holidays: 25,
bonusDayRate: 0.2,
},
}
]}
enableScheduleManagement={true}
enableHolidayBooking={true}
/>
```
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.