simple-calendar-js
Version:
A clean, modern, and feature-rich JavaScript calendar component with zero dependencies. Responsive design and intuitive navigation.
776 lines (651 loc) • 28.6 kB
Markdown
# Simple Calendar JS
A pure JavaScript calendar component with no dependencies. Features responsive design, multiple view modes, and customizable styling.
## Features
- **Pure JavaScript** - No jQuery or other dependencies
- **Three View Modes** - Month, Week, and Day views
- **Responsive Design** - Works on desktop, tablet, and mobile
- **Time-based Views** - Week and day views with customizable time slots
- **Fullday Mode** - Toggle between time-based and fullday event display
- **Multi-day Events** - Seamless event display across multiple days
- **Smart Event Fetching** - Callback-based event loading with intelligent caching
- **Event Callbacks** - Day click, event click, and state change handlers
- **Grid Border Control** - Customizable grid borders (both, vertical, horizontal, none)
- **Internationalization** - Full localization support for weekdays, months, and UI labels
- **Month/Year Dropdowns** - Quick navigation with clickable month and year selectors
- **Color Customization** - Comprehensive theming system with light/dark mode support
- **Enhanced Theme Detection** - Automatic theme detection for Next.js, Tailwind CSS, and other frameworks
- **Theme Integration** - Built-in dark theme with automatic color adaptation
- **Enhanced Navigation** - Transparent navigation buttons with theme-aware hover effects
- **Always-Visible Time Lines** - Hour and half-hour lines remain visible regardless of grid settings
- **Header Visibility Control** - Show/hide month, year, navigation, and view buttons independently
- **Smart Container Optimization** - Automatic layout optimization for small calendar containers
- **Improved Text Overflow** - Enhanced ellipsis behavior for event text in constrained spaces
- **Clean Interaction Design** - Removed distracting hover effects for professional appearance
- **CSS Prefix** - All classes prefixed with 'sc-' to avoid conflicts
- **Template Strings** - Clean HTML generation using template literals
- **Event Support** - Add, remove, and display events
- **Keyboard Navigation** - Arrow keys, T (today), M/W/D (views)
- **Memory Management** - Proper cleanup with destroy() method for SPAs
## Quick Start
```html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/simple-calendar-js.css">
</head>
<body>
<div id="calendar"></div>
<script src="js/simple-calendar-js.js"></script>
<script>
const calendar = new SimpleCalendarJs('#calendar', {
view: 'month',
date: new Date(),
fulldayMode: false,
events: []
});
</script>
</body>
</html>
```
## Configuration Options
```javascript
const calendar = new SimpleCalendarJs('#calendar', {
// View Configuration
view: 'month', // 'month', 'week', or 'day'
date: new Date(), // Initial date to display
fulldayMode: false, // Show fullday events only
// Time Configuration (for week/day views)
startHour: 6, // Start time for week/day view (0-23)
endHour: 22, // End time for week/day view (0-23)
timeSlotMinutes: 30, // Time slot intervals (currently supports 30)
// Visual Configuration
gridBorders: 'both', // 'both', 'vertical', 'horizontal', 'none'
eventBorders: false, // true/false - whether events should have borders
eventBorderColor: '#6c757d', // Color for event borders (when eventBorders: true)
defaultEventColor: '#4c6f94', // Default color for events without custom colors
// UI Element Visibility
showMonthButton: true, // true/false - show month view button
showWeekButton: true, // true/false - show week view button
showDayButton: true, // true/false - show day view button
showNavigation: true, // true/false - show navigation buttons (prev/next)
showTitle: true, // true/false - show entire title container (month/year)
showMonth: true, // true/false - show month in title (when showTitle is true)
showYear: true, // true/false - show year in title (when showTitle is true)
// Localization Options
weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
showWeekdayChars: null, // null = full weekday names, number = show first N characters
labels: { // UI labels for buttons and text
month: 'Month',
week: 'Week',
day: 'Day',
events: 'events', // Badge text (plural)
event: 'event', // Badge text (singular)
before: 'Before', // Time slot label for early times
after: 'After' // Time slot label for late times
},
// Color Customization
colors: {
// Light theme colors (defaults)
background: '#ffffff',
backgroundSecondary: '#f8f9fa',
backgroundTertiary: '#ecf0f1',
text: '#212529',
textSecondary: '#6c757d',
textMuted: '#adb5bd',
border: '#e9ecef',
borderLight: '#dee2e6',
accent: '#4c6f94',
accentHover: '#0056b3',
todayBg: '#e3f2fd',
todayText: '#dc3545',
hoverBg: '#f8f9fa',
// Dark theme colors (auto-applied when data-theme="dark")
dark: {
background: '#2d2d2d',
backgroundSecondary: '#3a3a3a',
backgroundTertiary: '#4a4a4a',
text: '#ffffff',
textSecondary: '#cccccc',
textMuted: '#888888',
border: '#444444',
borderLight: '#555555',
accent: '#4a90e2',
accentHover: '#357abd',
todayBg: '#1a2f4a',
todayText: '#ff6b6b',
hoverBg: '#2d2d2d'
}
},
// Data Configuration
events: [], // Array of event objects OR callback function
// Event Handlers
dayClick: null, // Function called when day is clicked
eventClick: null, // Function called when event is clicked
changeState: null // Function called when calendar state changes
});
```
## Localization
SimpleCalendarJs supports full internationalization with customizable text and date formats:
```javascript
const calendar = new SimpleCalendarJs('#calendar', {
// Portuguese example
weekdays: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'],
months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
showWeekdayChars: 3, // Show only first 3 characters: "Dom", "Seg", etc.
labels: {
month: 'Mês',
week: 'Semana',
day: 'Dia',
events: 'eventos',
event: 'evento',
before: 'Antes das',
after: 'Depois das'
}
});
// French example
const frenchCalendar = new SimpleCalendarJs('#calendar', {
weekdays: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
months: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
showWeekdayChars: 2, // Show first 2 characters: "Di", "Lu", etc.
labels: {
month: 'Mois',
week: 'Semaine',
day: 'Jour',
events: 'événements',
event: 'événement',
before: 'Avant',
after: 'Après'
}
});
```
### Weekday Display Options
- **`showWeekdayChars: null`** - Show full weekday names (default)
- **`showWeekdayChars: 3`** - Show first 3 characters ("Sun", "Mon", etc.)
- **`showWeekdayChars: 1`** - Show single character ("S", "M", etc.)
## Month/Year Navigation
In month view, clicking on the month or year title opens dropdown menus for quick navigation:
### Features
- **Month Dropdown** - Click month title to select any month
- **Year Dropdown** - Click year title to select from a range of years
- **Keyboard Support** - Navigate with arrow keys and Enter
- **Auto-scroll** - Current month/year automatically scrolls into view
- **Compact Design** - Minimal dropdown styling that adapts to themes
### Styling
The dropdowns automatically inherit the calendar's theme and can be customized via CSS:
```css
.sc-month-dropdown, .sc-year-dropdown {
/* Customize dropdown appearance */
max-height: 200px;
background: var(--sc-bg-secondary);
border: 1px solid var(--sc-border-color);
}
.sc-month-option:hover, .sc-year-option:hover {
background: var(--sc-hover-bg);
color: var(--sc-accent-color);
}
```
## Color Customization
SimpleCalendarJs provides a comprehensive color system that supports partial customization and automatic theme switching:
### Basic Color Override
```javascript
const calendar = new SimpleCalendarJs('#calendar', {
colors: {
background: '#f0f8ff', // Only override background
accent: '#ff6b6b' // Only override accent color
// All other colors use defaults
}
});
```
### Full Theme Customization
```javascript
const calendar = new SimpleCalendarJs('#calendar', {
colors: {
// Light theme colors
background: '#ffffff',
backgroundSecondary: '#f8f9fa',
backgroundTertiary: '#ecf0f1',
text: '#212529',
textSecondary: '#6c757d',
textMuted: '#adb5bd',
border: '#e9ecef',
borderLight: '#dee2e6',
accent: '#4c6f94',
accentHover: '#0056b3',
todayBg: '#e3f2fd',
todayText: '#dc3545',
hoverBg: '#f8f9fa',
// Dark theme colors (optional)
dark: {
background: '#1a1a1a',
backgroundSecondary: '#2d2d2d',
backgroundTertiary: '#3a3a3a',
text: '#ffffff',
textSecondary: '#cccccc',
textMuted: '#888888',
border: '#444444',
borderLight: '#555555',
accent: '#4a90e2',
accentHover: '#357abd',
todayBg: '#1a2f4a',
todayText: '#ff6b6b',
hoverBg: '#2d2d2d'
}
}
});
```
### Transparent Values
Any color property can be set to `'transparent'` for seamless integration:
```javascript
colors: {
background: 'transparent', // Calendar blends with page background
border: 'transparent', // Remove all borders
hoverBg: 'transparent' // Disable hover backgrounds
}
```
### Color Properties Reference
| Property | Description | Default (Light) | Default (Dark) |
|----------|-------------|-----------------|----------------|
| `background` | Main calendar background | `#ffffff` | `#2d2d2d` |
| `backgroundSecondary` | Secondary backgrounds | `#f8f9fa` | `#3a3a3a` |
| `backgroundTertiary` | Controls and headers | `#ecf0f1` | `#4a4a4a` |
| `text` | Primary text color | `#212529` | `#ffffff` |
| `textSecondary` | Secondary text | `#6c757d` | `#cccccc` |
| `textMuted` | Muted/disabled text | `#adb5bd` | `#888888` |
| `border` | Grid and element borders | `#e9ecef` | `#444444` |
| `borderLight` | Light accent borders | `#dee2e6` | `#555555` |
| `accent` | Active states and highlights | `#4c6f94` | `#4a90e2` |
| `accentHover` | Hover states | `#0056b3` | `#357abd` |
| `todayBg` | Today's date background | `#e3f2fd` | `#1a2f4a` |
| `todayText` | Today's date text | `#dc3545` | `#ff6b6b` |
| `hoverBg` | Hover backgrounds | `#f8f9fa` | `#2d2d2d` |
### Enhanced Theme Detection
The calendar features intelligent theme detection covering popular frameworks and systems:
**Automatic Detection Priority:**
1. **data-theme attribute** - `data-theme="dark"` (original system)
2. **Class-based themes** - `.dark` or `.light` classes on `html` or `body` (Next.js, Tailwind CSS)
3. **CSS custom properties** - `--theme` variable
4. **Alternative attributes** - `theme` attribute
5. **System preference** - `prefers-color-scheme: dark`
**Framework Compatibility:**
- **Next.js** with `next-themes` - Automatically detects `.dark` class
- **Tailwind CSS** - Supports Tailwind's dark mode classes
- **Custom systems** - Flexible detection for various theme implementations
- **Real-time updates** - Theme changes are detected and applied automatically
**Example Usage:**
```javascript
// Works automatically with Next.js themes
const calendar = new SimpleCalendarJs('#calendar', {
// No manual theme configuration needed
});
// Manual override still available
document.documentElement.setAttribute('data-theme', 'dark');
```
**Memory Management:**
The calendar includes proper cleanup with a `destroy()` method for Single Page Applications:
```javascript
calendar.destroy(); // Cleans up theme observers and event listeners
```
## Event Format
```javascript
// Single-day event with basic properties
const singleEvent = {
id: 1,
title: 'Meeting',
date: new Date('2023-12-25'),
time: '10:00 AM' // Optional: for time-based views
};
// Multi-day event with basic properties
const multiDayEvent = {
id: 2,
title: 'Conference',
startDate: new Date('2023-12-25'),
endDate: new Date('2023-12-27'),
time: '9:00 AM' // Optional: shown on start day
};
// Event with custom colors and styling
const coloredEvent = {
id: 3,
title: 'Important Meeting',
date: new Date('2023-12-25'),
time: '2:00 PM',
color: '#e74c3c', // Custom color (hex format)
colorIsGradient: true // Apply gradient effect to color
};
// Event with solid custom color
const solidColorEvent = {
id: 4,
title: 'Team Lunch',
date: new Date('2023-12-26'),
color: '#2ecc71', // Custom green color
colorIsGradient: false // Use solid color (default behavior)
};
// Event with gradient using default color
const defaultGradientEvent = {
id: 5,
title: 'Training Session',
date: new Date('2023-12-27'),
colorIsGradient: true // Use default color with gradient
};
```
### Event Color Properties
| Property | Type | Description |
|----------|------|-------------|
| `color` | string | Hex color code (e.g., '#e74c3c'). If not provided, uses `defaultEventColor` |
| `colorIsGradient` | boolean | When `true`, creates a subtle gradient effect. When `false` or omitted, uses solid color |
### Color Logic
1. **`event.color` + `colorIsGradient: true`** → Custom color with gradient effect
2. **`event.color` + `colorIsGradient: false`** → Custom solid color
3. **`colorIsGradient: true` (no color)** → Default color with gradient effect
4. **No color properties** → Default solid color
Text color (black or white) is automatically calculated for optimal contrast using WCAG guidelines.
## Event Callbacks
```javascript
const calendar = new SimpleCalendarJs('#calendar', {
// Dynamic event loading
events: function(dateRange) {
// Called with {startDate, endDate} for visible range
// Return array of events for this range
return fetchEventsFromAPI(dateRange.startDate, dateRange.endDate);
},
// Day click handler
dayClick: function(clickInfo, originalEvent) {
// clickInfo: {date, time} - time only for time-based views
console.log('Clicked on:', clickInfo.date, clickInfo.time);
},
// Event click handler
eventClick: function(event, clickInfo, originalEvent) {
// event: the clicked event object
// clickInfo: {date, time} - date/time where event was clicked
console.log('Clicked event:', event.title, 'at', clickInfo.time);
},
// State change handler
changeState: function(state) {
// state: {view, date, fulldayMode, startHour, endHour, timeSlotMinutes}
console.log('Calendar state changed:', state);
}
});
```
## API Methods
```javascript
// Navigation
calendar.navigate('next'); // Navigate to next period
calendar.navigate('prev'); // Navigate to previous period
calendar.goToDate(new Date()); // Go to specific date
calendar.goToToday(); // Go to today
// View switching
calendar.setView('month'); // 'month', 'week', 'day'
calendar.setFulldayMode(true); // Toggle fullday mode
// Event management
calendar.addEvent(event); // Add single event
calendar.removeEvent(eventId); // Remove event by ID
calendar.setEvents(eventsArray); // Replace all events
calendar.setEvents(callbackFunction); // Set dynamic event loading
// Visual customization
calendar.setGridBorders('none'); // 'both', 'vertical', 'horizontal', 'none'
calendar.setEventBorders(true); // Enable/disable event borders
calendar.setEventBorderColor('#ff0000'); // Set event border color
calendar.setDefaultEventColor('#3498db'); // Set default event color
// UI element visibility
calendar.setShowMonthButton(true); // Show/hide month view button
calendar.setShowWeekButton(true); // Show/hide week view button
calendar.setShowDayButton(true); // Show/hide day view button
calendar.setShowNavigation(true); // Show/hide navigation buttons
calendar.setShowTitle(true); // Show/hide entire title container
calendar.setShowMonth(true); // Show/hide month in title
calendar.setShowYear(true); // Show/hide year in title
calendar.setViewButtonsVisibility( // Set multiple button visibility at once
true, // month button
true, // week button
false // day button
);
// Memory management
calendar.destroy(); // Clean up observers and event listeners
```
## CSS Classes
All CSS classes are prefixed with `sc-` to prevent conflicts:
### Main Structure
- `.sc-calendar` - Main container
- `.sc-header` - Calendar header
- `.sc-content` - Content area
- `.sc-view-container` - View-specific container
### Views
- `.sc-month-view` - Month view container
- `.sc-week-view` - Week view container
- `.sc-day-view` - Day view container
- `.sc-fullday` - Fullday mode modifier
### Grid & Days
- `.sc-days-grid` - Grid container for days
- `.sc-day` - Individual day cell
- `.sc-day-number` - Day number text
- `.sc-today` - Today's date styling
- `.sc-other-month` - Days from other months
### Events
- `.sc-event-month`, `.sc-event-week`, `.sc-event-day`, `.sc-event-time` - Event containers
- `.sc-event-text` - Event text content
- `.sc-event-single` - Single-day event
- `.sc-event-start` - Multi-day event start
- `.sc-event-middle` - Multi-day event middle
- `.sc-event-end` - Multi-day event end
- `.sc-event-placeholder` - Transparent placeholder for multi-day alignment
### Event Count (Month View - Non-Fullday)
- `.sc-day-count-mode` - Day cell in count mode
- `.sc-day-content` - Container for day number and event count
- `.sc-event-count` - Event count badge with rounded corners
### Headers & Navigation
- `.sc-nav` - Navigation buttons container
- `.sc-title` - Month/date title
- `.sc-title-month` - Clickable month title (in month view)
- `.sc-title-year` - Clickable year title (in month view)
- `.sc-view-switcher` - View mode buttons
- `.sc-btn` - Button styling
### Dropdown Navigation
- `.sc-month-dropdown` - Month selection dropdown
- `.sc-year-dropdown` - Year selection dropdown
- `.sc-month-option` - Individual month option
- `.sc-year-option` - Individual year option
### Border Modifiers
- `.sc-borders-both` - Show all grid borders
- `.sc-borders-vertical` - Vertical grid borders only
- `.sc-borders-horizontal` - Horizontal grid borders only
- `.sc-borders-none` - No grid borders
- `.sc-event-borders` - Enable event borders
- `.sc-event-no-borders` - Disable event borders (default)
## CSS Custom Properties (Variables)
The calendar uses CSS custom properties for comprehensive theming. These are automatically managed by the color customization system, but can also be overridden directly:
### Event Colors
```css
.sc-calendar {
--sc-event-color: #4c6f94; /* Default event background color */
--sc-event-border-color: #6c757d; /* Event border color */
}
```
### Theme Colors (Auto-managed)
```css
.sc-calendar {
/* Main backgrounds */
--sc-bg-primary: #ffffff;
--sc-bg-secondary: #f8f9fa;
--sc-bg-tertiary: #ecf0f1;
/* Text colors */
--sc-text-primary: #212529;
--sc-text-secondary: #6c757d;
--sc-text-muted: #adb5bd;
/* Borders */
--sc-border-color: #e9ecef;
--sc-border-light: #dee2e6;
/* Interactive elements */
--sc-accent-color: #4c6f94;
--sc-accent-hover: #0056b3;
--sc-today-bg: #e3f2fd;
--sc-today-text: #dc3545;
--sc-hover-bg: #f8f9fa;
}
/* Dark theme variables (auto-applied with data-theme="dark") */
[data-theme="dark"] .sc-calendar {
--sc-bg-primary: #2d2d2d;
--sc-bg-secondary: #3a3a3a;
--sc-bg-tertiary: #4a4a4a;
--sc-text-primary: #ffffff;
--sc-text-secondary: #cccccc;
--sc-text-muted: #888888;
--sc-border-color: #444444;
--sc-border-light: #555555;
--sc-accent-color: #4a90e2;
--sc-accent-hover: #357abd;
--sc-today-bg: #1a2f4a;
--sc-today-text: #ff6b6b;
--sc-hover-bg: #2d2d2d;
}
```
### Manual Override Example
```css
/* Custom theme using CSS variables */
.sc-calendar {
--sc-bg-primary: #f0f8ff;
--sc-accent-color: #ff6b6b;
--sc-today-bg: #ffe4e1;
}
/* Dark theme integration */
[data-theme="dark"] .sc-calendar {
--sc-bg-primary: #1e1e1e;
--sc-accent-color: #ff8a80;
}
```
## Event Count Badges
In month view with `fulldayMode: false`, event counts are displayed as styled badges with theme-aware coloring:
- **Regular days**: Uses default event color with reduced opacity for background
- **Today**: Full default event color background with white text
- **Other month days**: Muted background with secondary text color
- **Theme adaptive**: Automatically adjusts colors for light/dark themes
- **Responsive**: Automatically adjusts size on mobile devices
- **Rounded corners**: Modern badge appearance with `border-radius: 10px`
### Badge Color Logic
- Background uses `color-mix()` function to blend event color with theme background
- Text color adapts to theme (darker in light mode, lighter in dark mode)
- Today's badge uses full event color saturation for emphasis
- Seamlessly integrates with custom color schemes
## Small Container Optimization
The calendar automatically optimizes its layout for small containers and constrained spaces:
### **Container Detection**
- **Automatic optimization** for calendars with height ≤ 500px
- **Responsive text sizing** based on container dimensions
- **Smart padding reduction** in tight spaces
### **Layout Improvements**
- **Flex/Grid overflow prevention** - Uses `min-height: 0` to allow proper content shrinking
- **Container hierarchy fixes** - Ensures all nested containers respect parent boundaries
- **Text ellipsis enhancement** - More aggressive text truncation in small spaces
### **Event Text Optimization**
- **Fullday mode fixes** - Event text properly constrained within event boundaries
- **Padding-aware sizing** - Text width accounts for container padding
- **Responsive font sizes** - Smaller fonts in compact containers
- **Enhanced ellipsis** - Earlier text truncation for better readability
### **Cross-View Consistency**
- **Month view** - Days shrink to fit container height
- **Week view** - Time slots and fullday events scale appropriately
- **Day view** - All elements respect container constraints
Example usage in small spaces:
```html
<div style="height: 400px; width: 300px;">
<div id="small-calendar"></div>
</div>
```
## Enhanced Styling Features
### Navigation Button Styling
- **Transparent Background**: Navigation arrows have transparent backgrounds in both themes
- **Theme-Aware Hover**: Hover effects use the default event color for consistency
- **Proper Contrast**: Arrow colors automatically adjust for light/dark themes
### View Button Styling
- **Active State**: Uses default event color when view button is active
- **Inactive State**: Transparent background with theme-appropriate text color
- **Consistent Theming**: Seamlessly adapts to color customization
### Time Lines Enhancement
- **Always Visible**: Hour and half-hour lines remain visible regardless of grid border settings
- **Proper Hierarchy**: Uses `!important` declarations to ensure visibility
- **Theme Integration**: Line colors adapt to current theme automatically
### Clean Interaction Design
- **Removed Hover Effects**: Day cells and time slots no longer show distracting hover backgrounds
- **Professional Appearance**: Cleaner, more focused user interface
- **Preserved Functionality**: All click interactions and cursor pointers remain intact
- **Better Visual Hierarchy**: User attention stays on important content like events and dates
### Today Highlighting
- **Enhanced Contrast**: Today's background is darker in dark mode for better visibility
- **Cross-View Consistency**: Today highlighting works consistently across month, week, and day views
- **Customizable Colors**: Today colors can be overridden via color customization system
### Page Integration
- **Scrollable Layout**: Calendar no longer uses fixed positioning, allowing page scrolling
- **Flexible Container**: Adapts to parent container constraints
- **Better Integration**: Easier to embed in existing page layouts
## Keyboard Shortcuts
- **Arrow Left/Right** - Navigate to previous/next period
- **T** - Go to today
- **M** - Switch to month view
- **W** - Switch to week view
- **D** - Switch to day view
## Time Format
Time strings should be in 12-hour format with AM/PM:
```javascript
'9:00 AM' // Valid
'2:30 PM' // Valid
'09:00' // Invalid
'14:30' // Invalid
```
## Multi-day Events
Multi-day events are automatically detected when `startDate` and `endDate` differ:
- **Start day**: Shows event title and colored bar
- **Middle days**: Shows only colored bar (seamless connection)
- **End day**: Shows only colored bar
Events spanning across weeks will continue seamlessly in the next row.
## Smart Event Caching
When using callback-based event loading, the calendar implements intelligent caching:
- Only fetches missing date ranges
- Merges overlapping ranges automatically
- Minimizes API calls when navigating
- Clears cache when `setEvents()` is called
## Color & Accessibility
The calendar automatically ensures good color contrast for accessibility:
### WCAG Compliance
- Text color (black or white) is automatically calculated for optimal contrast
- Uses WCAG relative luminance algorithm to determine text color
- Ensures contrast ratios meet accessibility standards
### Gradient Algorithm
When `colorIsGradient: true` is used:
1. Base color is used as the bottom of the gradient
2. Top color is calculated by adding 20 to each RGB component (capped at 255)
3. Creates a subtle top-to-bottom linear gradient effect
4. Text color is calculated based on the base color luminance
### Color Processing
```javascript
// Examples of color processing
const redEvent = {
color: '#e74c3c', // Red base color
colorIsGradient: true // Creates gradient from #ff6659 to #e74c3c
};
// Text color: white (due to dark base color)
const yellowEvent = {
color: '#f1c40f', // Yellow base color
colorIsGradient: true // Creates gradient from #fff323 to #f1c40f
};
// Text color: black (due to light base color)
```
## Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
## File Structure
```
simple-calendar-js/
├── css/
│ └── simple-calendar-js.css # Main stylesheet
├── js/
│ └── simple-calendar-js.js # Main JavaScript file
├── index.html # Demo page
├── README.md # This file
└── package.json # Package configuration
```
## License
**Personal and Non-Commercial Use License**
This project is free for personal, educational, and non-commercial use.
**Commercial use requires a separate license.** See [LICENSE](LICENSE) file for details.
For commercial licensing: simplecalendarjs@gmail.com