simple-calendar-js 2.0.3 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +451 -674
- package/dist/simple-calendar-js.min.css +13 -0
- package/dist/simple-calendar-js.min.js +15 -0
- package/frameworks/simple-calendar-js-angular.component.ts +292 -0
- package/frameworks/simple-calendar-js-react.jsx +161 -0
- package/frameworks/simple-calendar-js-vue.js +208 -0
- package/package.json +9 -9
- package/dist/SimpleCalendarJs.min.css +0 -10
- package/dist/SimpleCalendarJs.min.js +0 -10
package/README.md
CHANGED
|
@@ -1,748 +1,532 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SimpleCalendarJs
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A lightweight, zero-dependency JavaScript calendar component with internationalization support and framework wrappers for React, Vue, and Angular.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
4
7
|
|
|
5
8
|
## Features
|
|
6
9
|
|
|
7
|
-
- **
|
|
8
|
-
- **Three View Modes** - Month,
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
- **Zero Dependencies** - Pure vanilla JavaScript, no external libraries
|
|
11
|
+
- **Three View Modes** - Month, week, and day views with smooth transitions
|
|
12
|
+
- **Full Internationalization** - Built on Intl.DateTimeFormat API for native locale support
|
|
13
|
+
- **Framework Wrappers** - Official React, Vue 3, and Angular components included
|
|
14
|
+
- **Module System Support** - Works as UMD (CommonJS, AMD, ES modules, or browser global)
|
|
15
|
+
- **Dark Mode Ready** - Automatic dark theme detection and support
|
|
16
|
+
- **Async Event Loading** - Fetch events dynamically with `async/await` support
|
|
17
|
+
- **Responsive Design** - Adapts to any screen size
|
|
18
|
+
- **Customizable Styling** - CSS custom properties for easy theming
|
|
19
|
+
- **Accessible** - Semantic HTML with proper ARIA attributes
|
|
20
|
+
- **Small Bundle Size** - ~22KB minified JS, ~14KB minified CSS
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
### NPM
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install simple-calendar-js
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### CDN
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<link rel="stylesheet" href="https://unpkg.com/simple-calendar-js/dist/simple-calendar-js.min.css">
|
|
34
|
+
<script src="https://unpkg.com/simple-calendar-js/dist/simple-calendar-js.min.js"></script>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Manual Download
|
|
38
|
+
|
|
39
|
+
Download the files from the [dist/](dist/) folder and include them in your project.
|
|
32
40
|
|
|
33
41
|
## Quick Start
|
|
34
42
|
|
|
43
|
+
### Vanilla JavaScript
|
|
44
|
+
|
|
35
45
|
```html
|
|
36
46
|
<!DOCTYPE html>
|
|
37
47
|
<html>
|
|
38
48
|
<head>
|
|
39
|
-
|
|
49
|
+
<link rel="stylesheet" href="simple-calendar-js.css">
|
|
40
50
|
</head>
|
|
41
51
|
<body>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
|
|
52
|
+
<div id="calendar"></div>
|
|
53
|
+
|
|
54
|
+
<script src="simple-calendar-js.js"></script>
|
|
55
|
+
<script>
|
|
56
|
+
const calendar = new SimpleCalendarJs('#calendar', {
|
|
57
|
+
defaultView: 'month',
|
|
58
|
+
locale: 'en-US',
|
|
59
|
+
fetchEvents: async (startDate, endDate) => {
|
|
60
|
+
// Fetch events from your API
|
|
61
|
+
const response = await fetch(`/api/events?start=${startDate}&end=${endDate}`);
|
|
62
|
+
return await response.json();
|
|
63
|
+
},
|
|
64
|
+
onEventClick: (event, mouseEvent) => {
|
|
65
|
+
console.log('Event clicked:', event);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
53
69
|
</body>
|
|
54
70
|
</html>
|
|
55
71
|
```
|
|
56
72
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
showWeekButton: true, // true/false - show week view button
|
|
80
|
-
showDayButton: true, // true/false - show day view button
|
|
81
|
-
showNavigation: true, // true/false - show navigation buttons (prev/next)
|
|
82
|
-
showTitle: true, // true/false - show entire title container (month/year)
|
|
83
|
-
showMonth: true, // true/false - show month in title (when showTitle is true)
|
|
84
|
-
showYear: true, // true/false - show year in title (when showTitle is true)
|
|
85
|
-
|
|
86
|
-
// Localization Options
|
|
87
|
-
weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
|
88
|
-
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
89
|
-
showWeekdayChars: null, // null = full weekday names, number = show first N characters
|
|
90
|
-
labels: { // UI labels for buttons and text
|
|
91
|
-
month: 'Month',
|
|
92
|
-
week: 'Week',
|
|
93
|
-
day: 'Day',
|
|
94
|
-
events: 'events', // Badge text (plural)
|
|
95
|
-
event: 'event', // Badge text (singular)
|
|
96
|
-
before: 'Before', // Time slot label for early times
|
|
97
|
-
after: 'After' // Time slot label for late times
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
// Color Customization
|
|
101
|
-
colors: {
|
|
102
|
-
// Light theme colors (defaults)
|
|
103
|
-
background: '#ffffff',
|
|
104
|
-
backgroundSecondary: '#f8f9fa',
|
|
105
|
-
backgroundTertiary: '#ecf0f1',
|
|
106
|
-
text: '#212529',
|
|
107
|
-
textSecondary: '#6c757d',
|
|
108
|
-
textMuted: '#adb5bd',
|
|
109
|
-
border: '#e9ecef',
|
|
110
|
-
borderLight: '#dee2e6',
|
|
111
|
-
accent: '#4c6f94',
|
|
112
|
-
accentHover: '#0056b3',
|
|
113
|
-
todayBg: '#e3f2fd',
|
|
114
|
-
todayText: '#dc3545',
|
|
115
|
-
hoverBg: '#f8f9fa',
|
|
116
|
-
// Dark theme colors (auto-applied when data-theme="dark")
|
|
117
|
-
dark: {
|
|
118
|
-
background: '#2d2d2d',
|
|
119
|
-
backgroundSecondary: '#3a3a3a',
|
|
120
|
-
backgroundTertiary: '#4a4a4a',
|
|
121
|
-
text: '#ffffff',
|
|
122
|
-
textSecondary: '#cccccc',
|
|
123
|
-
textMuted: '#888888',
|
|
124
|
-
border: '#444444',
|
|
125
|
-
borderLight: '#555555',
|
|
126
|
-
accent: '#4a90e2',
|
|
127
|
-
accentHover: '#357abd',
|
|
128
|
-
todayBg: '#1a2f4a',
|
|
129
|
-
todayText: '#ff6b6b',
|
|
130
|
-
hoverBg: '#2d2d2d'
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
// Data Configuration
|
|
135
|
-
events: [], // Array of event objects OR callback function
|
|
136
|
-
|
|
137
|
-
// Event Handlers
|
|
138
|
-
dayClick: null, // Function called when day is clicked
|
|
139
|
-
eventClick: null, // Function called when event is clicked
|
|
140
|
-
changeState: null // Function called when calendar state changes
|
|
141
|
-
});
|
|
73
|
+
### React
|
|
74
|
+
|
|
75
|
+
```jsx
|
|
76
|
+
import SimpleCalendarJsReact from 'simple-calendar-js/frameworks/simple-calendar-js-react.jsx';
|
|
77
|
+
import 'simple-calendar-js/dist/simple-calendar-js.min.css';
|
|
78
|
+
|
|
79
|
+
function MyCalendar() {
|
|
80
|
+
const fetchEvents = async (startDate, endDate) => {
|
|
81
|
+
const res = await fetch(`/api/events?start=${startDate}&end=${endDate}`);
|
|
82
|
+
return await res.json();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<SimpleCalendarJsReact
|
|
87
|
+
defaultView="month"
|
|
88
|
+
locale="en-US"
|
|
89
|
+
fetchEvents={fetchEvents}
|
|
90
|
+
onEventClick={(event) => console.log(event)}
|
|
91
|
+
style={{ height: '600px' }}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
142
95
|
```
|
|
143
96
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
labels: {
|
|
171
|
-
month: 'Mois',
|
|
172
|
-
week: 'Semaine',
|
|
173
|
-
day: 'Jour',
|
|
174
|
-
events: 'événements',
|
|
175
|
-
event: 'événement',
|
|
176
|
-
before: 'Avant',
|
|
177
|
-
after: 'Après'
|
|
97
|
+
### Vue 3
|
|
98
|
+
|
|
99
|
+
```vue
|
|
100
|
+
<template>
|
|
101
|
+
<SimpleCalendarJsVue
|
|
102
|
+
:defaultView="'month'"
|
|
103
|
+
:locale="'en-US'"
|
|
104
|
+
:fetchEvents="fetchEvents"
|
|
105
|
+
@eventClick="handleEventClick"
|
|
106
|
+
:style="{ height: '600px' }"
|
|
107
|
+
/>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<script>
|
|
111
|
+
import SimpleCalendarJsVue from 'simple-calendar-js/frameworks/simple-calendar-js-vue.js';
|
|
112
|
+
import 'simple-calendar-js/dist/simple-calendar-js.min.css';
|
|
113
|
+
|
|
114
|
+
export default {
|
|
115
|
+
components: { SimpleCalendarJsVue },
|
|
116
|
+
methods: {
|
|
117
|
+
async fetchEvents(startDate, endDate) {
|
|
118
|
+
const res = await fetch(`/api/events?start=${startDate}&end=${endDate}`);
|
|
119
|
+
return await res.json();
|
|
120
|
+
},
|
|
121
|
+
handleEventClick(event) {
|
|
122
|
+
console.log('Event clicked:', event);
|
|
178
123
|
}
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Weekday Display Options
|
|
183
|
-
- **`showWeekdayChars: null`** - Show full weekday names (default)
|
|
184
|
-
- **`showWeekdayChars: 3`** - Show first 3 characters ("Sun", "Mon", etc.)
|
|
185
|
-
- **`showWeekdayChars: 1`** - Show single character ("S", "M", etc.)
|
|
186
|
-
|
|
187
|
-
## Month/Year Navigation
|
|
188
|
-
|
|
189
|
-
In month view, clicking on the month or year title opens dropdown menus for quick navigation:
|
|
190
|
-
|
|
191
|
-
### Features
|
|
192
|
-
- **Month Dropdown** - Click month title to select any month
|
|
193
|
-
- **Year Dropdown** - Click year title to select from a range of years
|
|
194
|
-
- **Keyboard Support** - Navigate with arrow keys and Enter
|
|
195
|
-
- **Auto-scroll** - Current month/year automatically scrolls into view
|
|
196
|
-
- **Compact Design** - Minimal dropdown styling that adapts to themes
|
|
197
|
-
|
|
198
|
-
### Styling
|
|
199
|
-
The dropdowns automatically inherit the calendar's theme and can be customized via CSS:
|
|
200
|
-
|
|
201
|
-
```css
|
|
202
|
-
.sc-month-dropdown, .sc-year-dropdown {
|
|
203
|
-
/* Customize dropdown appearance */
|
|
204
|
-
max-height: 200px;
|
|
205
|
-
background: var(--sc-bg-secondary);
|
|
206
|
-
border: 1px solid var(--sc-border-color);
|
|
124
|
+
}
|
|
207
125
|
}
|
|
126
|
+
</script>
|
|
127
|
+
```
|
|
208
128
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
129
|
+
### Angular
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { Component } from '@angular/core';
|
|
133
|
+
|
|
134
|
+
@Component({
|
|
135
|
+
selector: 'app-calendar',
|
|
136
|
+
template: `
|
|
137
|
+
<simple-calendar-js
|
|
138
|
+
[defaultView]="'month'"
|
|
139
|
+
[locale]="'en-US'"
|
|
140
|
+
[fetchEvents]="fetchEvents"
|
|
141
|
+
(eventClick)="handleEventClick($event)"
|
|
142
|
+
[style.height.px]="600"
|
|
143
|
+
></simple-calendar-js>
|
|
144
|
+
`
|
|
145
|
+
})
|
|
146
|
+
export class CalendarComponent {
|
|
147
|
+
async fetchEvents(startDate: Date, endDate: Date) {
|
|
148
|
+
const res = await fetch(`/api/events?start=${startDate}&end=${endDate}`);
|
|
149
|
+
return await res.json();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
handleEventClick(event: any) {
|
|
153
|
+
console.log('Event clicked:', event);
|
|
154
|
+
}
|
|
212
155
|
}
|
|
213
156
|
```
|
|
214
157
|
|
|
215
|
-
##
|
|
216
|
-
|
|
217
|
-
SimpleCalendarJs provides a comprehensive color system that supports partial customization and automatic theme switching:
|
|
158
|
+
## Configuration Options
|
|
218
159
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
160
|
+
| Option | Type | Default | Description |
|
|
161
|
+
|--------|------|---------|-------------|
|
|
162
|
+
| `defaultView` | string | `'month'` | Initial view: `'month'`, `'week'`, or `'day'` |
|
|
163
|
+
| `defaultDate` | Date | `new Date()` | Initial date to display |
|
|
164
|
+
| `weekStartsOn` | number | `0` | First day of week: `0` (Sunday) or `1` (Monday) |
|
|
165
|
+
| `locale` | string | `'default'` | Locale code for Intl API (e.g., `'en-US'`, `'fr-FR'`, `'ja-JP'`) |
|
|
166
|
+
| `use24Hour` | boolean | `false` | Use 24-hour time format |
|
|
167
|
+
| `showTimeInItems` | boolean | `true` | Show time in event items |
|
|
168
|
+
| `showGridLines` | boolean | `true` | Show calendar grid lines |
|
|
169
|
+
| `showToolbar` | boolean | `true` | Show the toolbar |
|
|
170
|
+
| `showTodayButton` | boolean | `true` | Show "Today" button |
|
|
171
|
+
| `showNavigation` | boolean | `true` | Show prev/next navigation arrows |
|
|
172
|
+
| `showTitle` | boolean | `true` | Show month/year title |
|
|
173
|
+
| `showYearPicker` | boolean | `true` | Enable year picker dropdown (month view) |
|
|
174
|
+
| `showViewSwitcher` | boolean | `true` | Show view switcher buttons |
|
|
175
|
+
| `showTooltips` | boolean | `true` | Show tooltips on hover for events |
|
|
176
|
+
| `enabledViews` | string[] | `['month', 'week', 'day']` | Available view modes |
|
|
177
|
+
| `primaryColor` | string | `'#4f46e5'` | Primary theme color (hex) |
|
|
178
|
+
| `fetchEvents` | function | `null` | Async function to fetch events: `async (start, end) => Event[]` |
|
|
179
|
+
| `onEventClick` | function | `null` | Callback when event is clicked: `(event, mouseEvent) => void` |
|
|
180
|
+
| `onSlotClick` | function | `null` | Callback when time slot is clicked: `(date, mouseEvent) => void` |
|
|
181
|
+
| `onViewChange` | function | `null` | Callback when view changes: `(view) => void` |
|
|
182
|
+
| `onNavigate` | function | `null` | Callback when date range changes: `(startDate, endDate) => void` |
|
|
183
|
+
|
|
184
|
+
## Event Object Format
|
|
185
|
+
|
|
186
|
+
Events returned by `fetchEvents` should follow this structure:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
interface CalendarEvent {
|
|
190
|
+
id: string | number; // Unique identifier
|
|
191
|
+
title: string; // Event title
|
|
192
|
+
start: Date; // Start date/time
|
|
193
|
+
end?: Date; // End date/time (optional, defaults to start)
|
|
194
|
+
allDay?: boolean; // All-day event flag (optional)
|
|
195
|
+
color?: string; // Custom color (hex, optional)
|
|
196
|
+
description?: string; // Event description (also used for tooltip if tooltip not provided)
|
|
197
|
+
tooltip?: string; // Custom tooltip text shown on hover (overrides description)
|
|
198
|
+
[key: string]: any; // Any additional custom properties
|
|
199
|
+
}
|
|
228
200
|
```
|
|
229
201
|
|
|
230
|
-
###
|
|
202
|
+
### Example Events
|
|
203
|
+
|
|
231
204
|
```javascript
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
background: '#1a1a1a',
|
|
252
|
-
backgroundSecondary: '#2d2d2d',
|
|
253
|
-
backgroundTertiary: '#3a3a3a',
|
|
254
|
-
text: '#ffffff',
|
|
255
|
-
textSecondary: '#cccccc',
|
|
256
|
-
textMuted: '#888888',
|
|
257
|
-
border: '#444444',
|
|
258
|
-
borderLight: '#555555',
|
|
259
|
-
accent: '#4a90e2',
|
|
260
|
-
accentHover: '#357abd',
|
|
261
|
-
todayBg: '#1a2f4a',
|
|
262
|
-
todayText: '#ff6b6b',
|
|
263
|
-
hoverBg: '#2d2d2d'
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
});
|
|
205
|
+
const events = [
|
|
206
|
+
{
|
|
207
|
+
id: 1,
|
|
208
|
+
title: 'Team Meeting',
|
|
209
|
+
start: new Date('2024-03-15T10:00:00'),
|
|
210
|
+
end: new Date('2024-03-15T11:00:00'),
|
|
211
|
+
color: '#3b82f6',
|
|
212
|
+
tooltip: 'Weekly team sync\nDiscuss Q1 roadmap and sprint planning'
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
id: 2,
|
|
216
|
+
title: 'Conference',
|
|
217
|
+
start: new Date('2024-03-20T00:00:00'),
|
|
218
|
+
end: new Date('2024-03-22T23:59:59'),
|
|
219
|
+
allDay: true,
|
|
220
|
+
color: '#10b981',
|
|
221
|
+
description: 'Tech Conference 2024\nDowntown Convention Center'
|
|
222
|
+
}
|
|
223
|
+
];
|
|
267
224
|
```
|
|
268
225
|
|
|
269
|
-
|
|
270
|
-
Any color property can be set to `'transparent'` for seamless integration:
|
|
226
|
+
## Tooltips
|
|
271
227
|
|
|
272
|
-
|
|
273
|
-
colors: {
|
|
274
|
-
background: 'transparent', // Calendar blends with page background
|
|
275
|
-
border: 'transparent', // Remove all borders
|
|
276
|
-
hoverBg: 'transparent' // Disable hover backgrounds
|
|
277
|
-
}
|
|
278
|
-
```
|
|
228
|
+
SimpleCalendarJs includes built-in tooltip support for displaying additional event information on hover.
|
|
279
229
|
|
|
280
|
-
###
|
|
281
|
-
|
|
282
|
-
| Property | Description | Default (Light) | Default (Dark) |
|
|
283
|
-
|----------|-------------|-----------------|----------------|
|
|
284
|
-
| `background` | Main calendar background | `#ffffff` | `#2d2d2d` |
|
|
285
|
-
| `backgroundSecondary` | Secondary backgrounds | `#f8f9fa` | `#3a3a3a` |
|
|
286
|
-
| `backgroundTertiary` | Controls and headers | `#ecf0f1` | `#4a4a4a` |
|
|
287
|
-
| `text` | Primary text color | `#212529` | `#ffffff` |
|
|
288
|
-
| `textSecondary` | Secondary text | `#6c757d` | `#cccccc` |
|
|
289
|
-
| `textMuted` | Muted/disabled text | `#adb5bd` | `#888888` |
|
|
290
|
-
| `border` | Grid and element borders | `#e9ecef` | `#444444` |
|
|
291
|
-
| `borderLight` | Light accent borders | `#dee2e6` | `#555555` |
|
|
292
|
-
| `accent` | Active states and highlights | `#4c6f94` | `#4a90e2` |
|
|
293
|
-
| `accentHover` | Hover states | `#0056b3` | `#357abd` |
|
|
294
|
-
| `todayBg` | Today's date background | `#e3f2fd` | `#1a2f4a` |
|
|
295
|
-
| `todayText` | Today's date text | `#dc3545` | `#ff6b6b` |
|
|
296
|
-
| `hoverBg` | Hover backgrounds | `#f8f9fa` | `#2d2d2d` |
|
|
297
|
-
|
|
298
|
-
### Enhanced Theme Detection
|
|
299
|
-
The calendar features intelligent theme detection covering popular frameworks and systems:
|
|
300
|
-
|
|
301
|
-
**Automatic Detection Priority:**
|
|
302
|
-
1. **data-theme attribute** - `data-theme="dark"` (original system)
|
|
303
|
-
2. **Class-based themes** - `.dark` or `.light` classes on `html` or `body` (Next.js, Tailwind CSS)
|
|
304
|
-
3. **CSS custom properties** - `--theme` variable
|
|
305
|
-
4. **Alternative attributes** - `theme` attribute
|
|
306
|
-
5. **System preference** - `prefers-color-scheme: dark`
|
|
307
|
-
|
|
308
|
-
**Framework Compatibility:**
|
|
309
|
-
- **Next.js** with `next-themes` - Automatically detects `.dark` class
|
|
310
|
-
- **Tailwind CSS** - Supports Tailwind's dark mode classes
|
|
311
|
-
- **Custom systems** - Flexible detection for various theme implementations
|
|
312
|
-
- **Real-time updates** - Theme changes are detected and applied automatically
|
|
313
|
-
|
|
314
|
-
**Example Usage:**
|
|
315
|
-
```javascript
|
|
316
|
-
// Works automatically with Next.js themes
|
|
317
|
-
const calendar = new SimpleCalendarJs('#calendar', {
|
|
318
|
-
// No manual theme configuration needed
|
|
319
|
-
});
|
|
230
|
+
### How Tooltips Work
|
|
320
231
|
|
|
321
|
-
|
|
322
|
-
document.documentElement.setAttribute('data-theme', 'dark');
|
|
323
|
-
```
|
|
232
|
+
Tooltips appear when you hover over an event for 400ms. They display content based on the following priority:
|
|
324
233
|
|
|
325
|
-
**
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
calendar.destroy(); // Cleans up theme observers and event listeners
|
|
329
|
-
```
|
|
234
|
+
1. **`tooltip` property** (highest priority) - Custom tooltip text
|
|
235
|
+
2. **`description` property** - Falls back if no tooltip is provided
|
|
236
|
+
3. **`title` property** - Falls back if neither tooltip nor description is provided
|
|
330
237
|
|
|
331
|
-
|
|
238
|
+
### Basic Usage
|
|
332
239
|
|
|
333
240
|
```javascript
|
|
334
|
-
|
|
335
|
-
|
|
241
|
+
const events = [
|
|
242
|
+
{
|
|
336
243
|
id: 1,
|
|
337
|
-
title: 'Meeting',
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const multiDayEvent = {
|
|
244
|
+
title: 'Team Meeting',
|
|
245
|
+
start: new Date('2024-03-15T10:00:00'),
|
|
246
|
+
end: new Date('2024-03-15T11:00:00'),
|
|
247
|
+
tooltip: 'Weekly team sync\nDiscuss Q1 roadmap' // Custom tooltip
|
|
248
|
+
},
|
|
249
|
+
{
|
|
344
250
|
id: 2,
|
|
345
|
-
title: '
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Event with custom colors and styling
|
|
352
|
-
const coloredEvent = {
|
|
251
|
+
title: 'Client Call',
|
|
252
|
+
start: new Date('2024-03-15T14:00:00'),
|
|
253
|
+
end: new Date('2024-03-15T15:00:00'),
|
|
254
|
+
description: 'Requirements gathering\nPrepare demo' // Used as tooltip
|
|
255
|
+
},
|
|
256
|
+
{
|
|
353
257
|
id: 3,
|
|
354
|
-
title: '
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
// Event with solid custom color
|
|
362
|
-
const solidColorEvent = {
|
|
363
|
-
id: 4,
|
|
364
|
-
title: 'Team Lunch',
|
|
365
|
-
date: new Date('2023-12-26'),
|
|
366
|
-
color: '#2ecc71', // Custom green color
|
|
367
|
-
colorIsGradient: false // Use solid color (default behavior)
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
// Event with gradient using default color
|
|
371
|
-
const defaultGradientEvent = {
|
|
372
|
-
id: 5,
|
|
373
|
-
title: 'Training Session',
|
|
374
|
-
date: new Date('2023-12-27'),
|
|
375
|
-
colorIsGradient: true // Use default color with gradient
|
|
376
|
-
};
|
|
258
|
+
title: 'Code Review',
|
|
259
|
+
start: new Date('2024-03-15T16:00:00'),
|
|
260
|
+
end: new Date('2024-03-15T17:00:00')
|
|
261
|
+
// No tooltip/description - will show title
|
|
262
|
+
}
|
|
263
|
+
];
|
|
377
264
|
```
|
|
378
265
|
|
|
379
|
-
###
|
|
380
|
-
|
|
381
|
-
| Property | Type | Description |
|
|
382
|
-
|----------|------|-------------|
|
|
383
|
-
| `color` | string | Hex color code (e.g., '#e74c3c'). If not provided, uses `defaultEventColor` |
|
|
384
|
-
| `colorIsGradient` | boolean | When `true`, creates a subtle gradient effect. When `false` or omitted, uses solid color |
|
|
385
|
-
|
|
386
|
-
### Color Logic
|
|
387
|
-
1. **`event.color` + `colorIsGradient: true`** → Custom color with gradient effect
|
|
388
|
-
2. **`event.color` + `colorIsGradient: false`** → Custom solid color
|
|
389
|
-
3. **`colorIsGradient: true` (no color)** → Default color with gradient effect
|
|
390
|
-
4. **No color properties** → Default solid color
|
|
266
|
+
### Multiline Tooltips
|
|
391
267
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
## Event Callbacks
|
|
268
|
+
Use `\n` (newline character) in your tooltip or description text to create multiple lines:
|
|
395
269
|
|
|
396
270
|
```javascript
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
// Day click handler
|
|
406
|
-
dayClick: function(clickInfo, originalEvent) {
|
|
407
|
-
// clickInfo: {date, time} - time only for time-based views
|
|
408
|
-
console.log('Clicked on:', clickInfo.date, clickInfo.time);
|
|
409
|
-
},
|
|
410
|
-
|
|
411
|
-
// Event click handler
|
|
412
|
-
eventClick: function(event, clickInfo, originalEvent) {
|
|
413
|
-
// event: the clicked event object
|
|
414
|
-
// clickInfo: {date, time} - date/time where event was clicked
|
|
415
|
-
console.log('Clicked event:', event.title, 'at', clickInfo.time);
|
|
416
|
-
},
|
|
417
|
-
|
|
418
|
-
// State change handler
|
|
419
|
-
changeState: function(state) {
|
|
420
|
-
// state: {view, date, fulldayMode, startHour, endHour, timeSlotMinutes}
|
|
421
|
-
console.log('Calendar state changed:', state);
|
|
422
|
-
}
|
|
423
|
-
});
|
|
271
|
+
{
|
|
272
|
+
id: 1,
|
|
273
|
+
title: 'Project Kickoff',
|
|
274
|
+
start: new Date('2024-03-20T09:00:00'),
|
|
275
|
+
end: new Date('2024-03-20T10:30:00'),
|
|
276
|
+
tooltip: 'Project Kickoff Meeting\n\nAgenda:\n- Introductions\n- Timeline review\n- Q&A session\n\nLocation: Conference Room A'
|
|
277
|
+
}
|
|
424
278
|
```
|
|
425
279
|
|
|
426
|
-
|
|
280
|
+
### Tooltip Features
|
|
427
281
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
calendar.goToDate(new Date()); // Go to specific date
|
|
433
|
-
calendar.goToToday(); // Go to today
|
|
434
|
-
|
|
435
|
-
// View switching
|
|
436
|
-
calendar.setView('month'); // 'month', 'week', 'day'
|
|
437
|
-
calendar.setFulldayMode(true); // Toggle fullday mode
|
|
438
|
-
|
|
439
|
-
// Event management
|
|
440
|
-
calendar.addEvent(event); // Add single event
|
|
441
|
-
calendar.removeEvent(eventId); // Remove event by ID
|
|
442
|
-
calendar.setEvents(eventsArray); // Replace all events
|
|
443
|
-
calendar.setEvents(callbackFunction); // Set dynamic event loading
|
|
444
|
-
|
|
445
|
-
// Visual customization
|
|
446
|
-
calendar.setGridBorders('none'); // 'both', 'vertical', 'horizontal', 'none'
|
|
447
|
-
calendar.setEventBorders(true); // Enable/disable event borders
|
|
448
|
-
calendar.setEventBorderColor('#ff0000'); // Set event border color
|
|
449
|
-
calendar.setDefaultEventColor('#3498db'); // Set default event color
|
|
450
|
-
|
|
451
|
-
// UI element visibility
|
|
452
|
-
calendar.setShowMonthButton(true); // Show/hide month view button
|
|
453
|
-
calendar.setShowWeekButton(true); // Show/hide week view button
|
|
454
|
-
calendar.setShowDayButton(true); // Show/hide day view button
|
|
455
|
-
calendar.setShowNavigation(true); // Show/hide navigation buttons
|
|
456
|
-
calendar.setShowTitle(true); // Show/hide entire title container
|
|
457
|
-
calendar.setShowMonth(true); // Show/hide month in title
|
|
458
|
-
calendar.setShowYear(true); // Show/hide year in title
|
|
459
|
-
calendar.setViewButtonsVisibility( // Set multiple button visibility at once
|
|
460
|
-
true, // month button
|
|
461
|
-
true, // week button
|
|
462
|
-
false // day button
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
// Memory management
|
|
466
|
-
calendar.destroy(); // Clean up observers and event listeners
|
|
467
|
-
```
|
|
282
|
+
- **Smart Positioning**: Tooltips automatically adjust their position to stay visible:
|
|
283
|
+
- Events near the **top** of the viewport: tooltip shows below
|
|
284
|
+
- Events near the **right edge**: tooltip aligns to the right
|
|
285
|
+
- Events near the **left edge**: tooltip aligns to the left
|
|
468
286
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
- `.sc-calendar` - Main container
|
|
475
|
-
- `.sc-header` - Calendar header
|
|
476
|
-
- `.sc-content` - Content area
|
|
477
|
-
- `.sc-view-container` - View-specific container
|
|
478
|
-
|
|
479
|
-
### Views
|
|
480
|
-
- `.sc-month-view` - Month view container
|
|
481
|
-
- `.sc-week-view` - Week view container
|
|
482
|
-
- `.sc-day-view` - Day view container
|
|
483
|
-
- `.sc-fullday` - Fullday mode modifier
|
|
484
|
-
|
|
485
|
-
### Grid & Days
|
|
486
|
-
- `.sc-days-grid` - Grid container for days
|
|
487
|
-
- `.sc-day` - Individual day cell
|
|
488
|
-
- `.sc-day-number` - Day number text
|
|
489
|
-
- `.sc-today` - Today's date styling
|
|
490
|
-
- `.sc-other-month` - Days from other months
|
|
491
|
-
|
|
492
|
-
### Events
|
|
493
|
-
- `.sc-event-month`, `.sc-event-week`, `.sc-event-day`, `.sc-event-time` - Event containers
|
|
494
|
-
- `.sc-event-text` - Event text content
|
|
495
|
-
- `.sc-event-single` - Single-day event
|
|
496
|
-
- `.sc-event-start` - Multi-day event start
|
|
497
|
-
- `.sc-event-middle` - Multi-day event middle
|
|
498
|
-
- `.sc-event-end` - Multi-day event end
|
|
499
|
-
- `.sc-event-placeholder` - Transparent placeholder for multi-day alignment
|
|
500
|
-
|
|
501
|
-
### Event Count (Month View - Non-Fullday)
|
|
502
|
-
- `.sc-day-count-mode` - Day cell in count mode
|
|
503
|
-
- `.sc-day-content` - Container for day number and event count
|
|
504
|
-
- `.sc-event-count` - Event count badge with rounded corners
|
|
505
|
-
|
|
506
|
-
### Headers & Navigation
|
|
507
|
-
- `.sc-nav` - Navigation buttons container
|
|
508
|
-
- `.sc-title` - Month/date title
|
|
509
|
-
- `.sc-title-month` - Clickable month title (in month view)
|
|
510
|
-
- `.sc-title-year` - Clickable year title (in month view)
|
|
511
|
-
- `.sc-view-switcher` - View mode buttons
|
|
512
|
-
- `.sc-btn` - Button styling
|
|
513
|
-
|
|
514
|
-
### Dropdown Navigation
|
|
515
|
-
- `.sc-month-dropdown` - Month selection dropdown
|
|
516
|
-
- `.sc-year-dropdown` - Year selection dropdown
|
|
517
|
-
- `.sc-month-option` - Individual month option
|
|
518
|
-
- `.sc-year-option` - Individual year option
|
|
519
|
-
|
|
520
|
-
### Border Modifiers
|
|
521
|
-
- `.sc-borders-both` - Show all grid borders
|
|
522
|
-
- `.sc-borders-vertical` - Vertical grid borders only
|
|
523
|
-
- `.sc-borders-horizontal` - Horizontal grid borders only
|
|
524
|
-
- `.sc-borders-none` - No grid borders
|
|
525
|
-
- `.sc-event-borders` - Enable event borders
|
|
526
|
-
- `.sc-event-no-borders` - Disable event borders (default)
|
|
527
|
-
|
|
528
|
-
## CSS Custom Properties (Variables)
|
|
529
|
-
|
|
530
|
-
The calendar uses CSS custom properties for comprehensive theming. These are automatically managed by the color customization system, but can also be overridden directly:
|
|
531
|
-
|
|
532
|
-
### Event Colors
|
|
533
|
-
```css
|
|
534
|
-
.sc-calendar {
|
|
535
|
-
--sc-event-color: #4c6f94; /* Default event background color */
|
|
536
|
-
--sc-event-border-color: #6c757d; /* Event border color */
|
|
537
|
-
}
|
|
538
|
-
```
|
|
287
|
+
- **Visual Design**:
|
|
288
|
+
- Dark background with rounded corners
|
|
289
|
+
- Small arrow pointing to the event
|
|
290
|
+
- Smooth fade-in animation (400ms delay)
|
|
291
|
+
- Supports both light and dark themes
|
|
539
292
|
|
|
540
|
-
|
|
541
|
-
```css
|
|
542
|
-
.sc-calendar {
|
|
543
|
-
/* Main backgrounds */
|
|
544
|
-
--sc-bg-primary: #ffffff;
|
|
545
|
-
--sc-bg-secondary: #f8f9fa;
|
|
546
|
-
--sc-bg-tertiary: #ecf0f1;
|
|
547
|
-
|
|
548
|
-
/* Text colors */
|
|
549
|
-
--sc-text-primary: #212529;
|
|
550
|
-
--sc-text-secondary: #6c757d;
|
|
551
|
-
--sc-text-muted: #adb5bd;
|
|
552
|
-
|
|
553
|
-
/* Borders */
|
|
554
|
-
--sc-border-color: #e9ecef;
|
|
555
|
-
--sc-border-light: #dee2e6;
|
|
556
|
-
|
|
557
|
-
/* Interactive elements */
|
|
558
|
-
--sc-accent-color: #4c6f94;
|
|
559
|
-
--sc-accent-hover: #0056b3;
|
|
560
|
-
--sc-today-bg: #e3f2fd;
|
|
561
|
-
--sc-today-text: #dc3545;
|
|
562
|
-
--sc-hover-bg: #f8f9fa;
|
|
563
|
-
}
|
|
293
|
+
- **Responsive**: Tooltips overflow outside calendar boundaries to ensure full visibility
|
|
564
294
|
|
|
565
|
-
|
|
566
|
-
[data-theme="dark"] .sc-calendar {
|
|
567
|
-
--sc-bg-primary: #2d2d2d;
|
|
568
|
-
--sc-bg-secondary: #3a3a3a;
|
|
569
|
-
--sc-bg-tertiary: #4a4a4a;
|
|
570
|
-
--sc-text-primary: #ffffff;
|
|
571
|
-
--sc-text-secondary: #cccccc;
|
|
572
|
-
--sc-text-muted: #888888;
|
|
573
|
-
--sc-border-color: #444444;
|
|
574
|
-
--sc-border-light: #555555;
|
|
575
|
-
--sc-accent-color: #4a90e2;
|
|
576
|
-
--sc-accent-hover: #357abd;
|
|
577
|
-
--sc-today-bg: #1a2f4a;
|
|
578
|
-
--sc-today-text: #ff6b6b;
|
|
579
|
-
--sc-hover-bg: #2d2d2d;
|
|
580
|
-
}
|
|
581
|
-
```
|
|
295
|
+
### Disabling Tooltips
|
|
582
296
|
|
|
583
|
-
|
|
584
|
-
```css
|
|
585
|
-
/* Custom theme using CSS variables */
|
|
586
|
-
.sc-calendar {
|
|
587
|
-
--sc-bg-primary: #f0f8ff;
|
|
588
|
-
--sc-accent-color: #ff6b6b;
|
|
589
|
-
--sc-today-bg: #ffe4e1;
|
|
590
|
-
}
|
|
297
|
+
You can disable tooltips globally using the `showTooltips` option:
|
|
591
298
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
299
|
+
```javascript
|
|
300
|
+
const calendar = new SimpleCalendarJs('#calendar', {
|
|
301
|
+
showTooltips: false, // Disable all tooltips
|
|
302
|
+
fetchEvents: async (start, end) => { ... }
|
|
303
|
+
});
|
|
597
304
|
```
|
|
598
305
|
|
|
599
|
-
|
|
306
|
+
### Styling Tooltips
|
|
600
307
|
|
|
601
|
-
|
|
308
|
+
Tooltips use CSS custom properties and can be customized:
|
|
602
309
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
-
|
|
606
|
-
-
|
|
607
|
-
-
|
|
608
|
-
-
|
|
310
|
+
```css
|
|
311
|
+
:root {
|
|
312
|
+
--cal-tooltip-bg: #1f2937; /* Background color */
|
|
313
|
+
--cal-tooltip-text: #f9fafb; /* Text color */
|
|
314
|
+
--cal-tooltip-border: #374151; /* Border color */
|
|
315
|
+
--cal-tooltip-max-width: 250px; /* Maximum width */
|
|
316
|
+
--cal-tooltip-padding: 8px 12px; /* Inner padding */
|
|
317
|
+
--cal-tooltip-radius: 6px; /* Border radius */
|
|
318
|
+
--cal-tooltip-font-size: 12px; /* Font size */
|
|
319
|
+
--cal-tooltip-offset: 8px; /* Distance from event */
|
|
320
|
+
}
|
|
321
|
+
```
|
|
609
322
|
|
|
610
|
-
###
|
|
611
|
-
- Background uses `color-mix()` function to blend event color with theme background
|
|
612
|
-
- Text color adapts to theme (darker in light mode, lighter in dark mode)
|
|
613
|
-
- Today's badge uses full event color saturation for emphasis
|
|
614
|
-
- Seamlessly integrates with custom color schemes
|
|
323
|
+
### Limitations
|
|
615
324
|
|
|
616
|
-
|
|
325
|
+
- Tooltips display **plain text only** (no HTML rendering)
|
|
326
|
+
- Special characters are automatically escaped for security
|
|
327
|
+
- Maximum width is 250px by default (can be customized via CSS variables)
|
|
617
328
|
|
|
618
|
-
|
|
329
|
+
## API Methods
|
|
619
330
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
- **Smart padding reduction** in tight spaces
|
|
331
|
+
```javascript
|
|
332
|
+
// Switch view
|
|
333
|
+
calendar.setView('week');
|
|
624
334
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
-
|
|
628
|
-
- **Text ellipsis enhancement** - More aggressive text truncation in small spaces
|
|
335
|
+
// Navigate forward/backward
|
|
336
|
+
calendar.navigate(1); // Next period
|
|
337
|
+
calendar.navigate(-1); // Previous period
|
|
629
338
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
- **Padding-aware sizing** - Text width accounts for container padding
|
|
633
|
-
- **Responsive font sizes** - Smaller fonts in compact containers
|
|
634
|
-
- **Enhanced ellipsis** - Earlier text truncation for better readability
|
|
339
|
+
// Jump to specific date
|
|
340
|
+
calendar.goToDate(new Date('2024-12-25'));
|
|
635
341
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
- **Week view** - Time slots and fullday events scale appropriately
|
|
639
|
-
- **Day view** - All elements respect container constraints
|
|
342
|
+
// Jump to today
|
|
343
|
+
calendar.goToToday();
|
|
640
344
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
<div style="height: 400px; width: 300px;">
|
|
644
|
-
<div id="small-calendar"></div>
|
|
645
|
-
</div>
|
|
345
|
+
// Cleanup (important for SPAs)
|
|
346
|
+
calendar.destroy();
|
|
646
347
|
```
|
|
647
348
|
|
|
648
|
-
##
|
|
649
|
-
|
|
650
|
-
### Navigation Button Styling
|
|
651
|
-
- **Transparent Background**: Navigation arrows have transparent backgrounds in both themes
|
|
652
|
-
- **Theme-Aware Hover**: Hover effects use the default event color for consistency
|
|
653
|
-
- **Proper Contrast**: Arrow colors automatically adjust for light/dark themes
|
|
349
|
+
## Internationalization
|
|
654
350
|
|
|
655
|
-
|
|
656
|
-
- **Active State**: Uses default event color when view button is active
|
|
657
|
-
- **Inactive State**: Transparent background with theme-appropriate text color
|
|
658
|
-
- **Consistent Theming**: Seamlessly adapts to color customization
|
|
351
|
+
SimpleCalendarJs uses the native Intl.DateTimeFormat API for full locale support. Simply pass a valid locale code:
|
|
659
352
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
- **Removed Hover Effects**: Day cells and time slots no longer show distracting hover backgrounds
|
|
667
|
-
- **Professional Appearance**: Cleaner, more focused user interface
|
|
668
|
-
- **Preserved Functionality**: All click interactions and cursor pointers remain intact
|
|
669
|
-
- **Better Visual Hierarchy**: User attention stays on important content like events and dates
|
|
353
|
+
```javascript
|
|
354
|
+
// French
|
|
355
|
+
const calendar = new SimpleCalendarJs('#calendar', {
|
|
356
|
+
locale: 'fr-FR',
|
|
357
|
+
weekStartsOn: 1 // Monday
|
|
358
|
+
});
|
|
670
359
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
360
|
+
// Japanese
|
|
361
|
+
const calendar = new SimpleCalendarJs('#calendar', {
|
|
362
|
+
locale: 'ja-JP'
|
|
363
|
+
});
|
|
675
364
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
-
|
|
679
|
-
|
|
365
|
+
// Arabic (RTL support automatic)
|
|
366
|
+
const calendar = new SimpleCalendarJs('#calendar', {
|
|
367
|
+
locale: 'ar-SA'
|
|
368
|
+
});
|
|
369
|
+
```
|
|
680
370
|
|
|
681
|
-
|
|
371
|
+
Supported locales include: `en-US`, `en-GB`, `fr-FR`, `de-DE`, `es-ES`, `it-IT`, `pt-PT`, `pt-BR`, `ja-JP`, `zh-CN`, `ko-KR`, `ar-SA`, `ru-RU`, `tr-TR`, and [many more](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#locales).
|
|
682
372
|
|
|
683
|
-
|
|
684
|
-
- **T** - Go to today
|
|
685
|
-
- **M** - Switch to month view
|
|
686
|
-
- **W** - Switch to week view
|
|
687
|
-
- **D** - Switch to day view
|
|
373
|
+
## Dark Mode
|
|
688
374
|
|
|
689
|
-
|
|
375
|
+
Dark mode is automatically detected from the user's system preferences. You can also manually toggle it:
|
|
690
376
|
|
|
691
|
-
Time strings should be in 12-hour format with AM/PM:
|
|
692
377
|
```javascript
|
|
693
|
-
|
|
694
|
-
'
|
|
695
|
-
|
|
696
|
-
|
|
378
|
+
// Set data-theme attribute on <html> or <body>
|
|
379
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
380
|
+
|
|
381
|
+
// Or add a CSS class
|
|
382
|
+
document.documentElement.classList.add('dark');
|
|
697
383
|
```
|
|
698
384
|
|
|
699
|
-
|
|
385
|
+
For framework wrappers, use the `darkMode` prop:
|
|
700
386
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
- **End day**: Shows only colored bar
|
|
387
|
+
```jsx
|
|
388
|
+
// React
|
|
389
|
+
<SimpleCalendarJsReact darkMode={isDark} />
|
|
705
390
|
|
|
706
|
-
|
|
391
|
+
// Vue
|
|
392
|
+
<SimpleCalendarJsVue :darkMode="isDark" />
|
|
707
393
|
|
|
708
|
-
|
|
394
|
+
// Angular
|
|
395
|
+
<simple-calendar-js [darkMode]="isDark"></simple-calendar-js>
|
|
396
|
+
```
|
|
709
397
|
|
|
710
|
-
|
|
711
|
-
- Only fetches missing date ranges
|
|
712
|
-
- Merges overlapping ranges automatically
|
|
713
|
-
- Minimizes API calls when navigating
|
|
714
|
-
- Clears cache when `setEvents()` is called
|
|
398
|
+
## Styling & Theming
|
|
715
399
|
|
|
716
|
-
|
|
400
|
+
Customize the calendar appearance using CSS custom properties:
|
|
717
401
|
|
|
718
|
-
|
|
402
|
+
```css
|
|
403
|
+
.uc-calendar {
|
|
404
|
+
/* Primary color */
|
|
405
|
+
--cal-primary: #4f46e5;
|
|
406
|
+
--cal-primary-dark: #4338ca;
|
|
407
|
+
--cal-primary-light: #eef2ff;
|
|
408
|
+
|
|
409
|
+
/* Background colors */
|
|
410
|
+
--cal-bg: #ffffff;
|
|
411
|
+
--cal-bg-secondary: #f9fafb;
|
|
412
|
+
|
|
413
|
+
/* Text colors */
|
|
414
|
+
--cal-text: #111827;
|
|
415
|
+
--cal-text-subtle: #6b7280;
|
|
416
|
+
|
|
417
|
+
/* Borders */
|
|
418
|
+
--cal-border: #e5e7eb;
|
|
419
|
+
|
|
420
|
+
/* Today indicator */
|
|
421
|
+
--cal-today-bg: #eef2ff;
|
|
422
|
+
--cal-today-text: var(--cal-primary);
|
|
423
|
+
|
|
424
|
+
/* Events */
|
|
425
|
+
--cal-event-bg: var(--cal-primary);
|
|
426
|
+
--cal-event-text: #ffffff;
|
|
427
|
+
|
|
428
|
+
/* Sizing */
|
|
429
|
+
--cal-font-size: 13px;
|
|
430
|
+
--cal-hour-height: 60px;
|
|
431
|
+
}
|
|
432
|
+
```
|
|
719
433
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
434
|
+
All styles are scoped under `.uc-calendar` to prevent conflicts with your existing CSS.
|
|
435
|
+
|
|
436
|
+
## Framework Wrapper APIs
|
|
437
|
+
|
|
438
|
+
### React
|
|
439
|
+
|
|
440
|
+
```jsx
|
|
441
|
+
import { useRef } from 'react';
|
|
442
|
+
import SimpleCalendarJsReact from 'simple-calendar-js/frameworks/simple-calendar-js-react.jsx';
|
|
443
|
+
|
|
444
|
+
function MyComponent() {
|
|
445
|
+
const calendarRef = useRef();
|
|
446
|
+
|
|
447
|
+
const handleSomeAction = () => {
|
|
448
|
+
// Access imperative methods
|
|
449
|
+
calendarRef.current.goToToday();
|
|
450
|
+
calendarRef.current.setView('week');
|
|
451
|
+
calendarRef.current.navigate(1);
|
|
452
|
+
calendarRef.current.goToDate(new Date('2024-12-25'));
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
return (
|
|
456
|
+
<SimpleCalendarJsReact
|
|
457
|
+
ref={calendarRef}
|
|
458
|
+
defaultView="month"
|
|
459
|
+
fetchEvents={fetchEvents}
|
|
460
|
+
onEventClick={(event) => console.log(event)}
|
|
461
|
+
onSlotClick={(date) => console.log('Clicked:', date)}
|
|
462
|
+
onViewChange={(view) => console.log('View:', view)}
|
|
463
|
+
onNavigate={(start, end) => console.log('Range:', start, end)}
|
|
464
|
+
/>
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
```
|
|
724
468
|
|
|
725
|
-
###
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
469
|
+
### Vue 3
|
|
470
|
+
|
|
471
|
+
```vue
|
|
472
|
+
<template>
|
|
473
|
+
<SimpleCalendarJsVue
|
|
474
|
+
ref="calendar"
|
|
475
|
+
:defaultView="'month'"
|
|
476
|
+
:fetchEvents="fetchEvents"
|
|
477
|
+
@eventClick="handleEventClick"
|
|
478
|
+
@slotClick="handleSlotClick"
|
|
479
|
+
@viewChange="handleViewChange"
|
|
480
|
+
@navigate="handleNavigate"
|
|
481
|
+
/>
|
|
482
|
+
</template>
|
|
483
|
+
|
|
484
|
+
<script>
|
|
485
|
+
export default {
|
|
486
|
+
methods: {
|
|
487
|
+
someAction() {
|
|
488
|
+
// Access imperative methods
|
|
489
|
+
this.$refs.calendar.goToToday();
|
|
490
|
+
this.$refs.calendar.setView('week');
|
|
491
|
+
this.$refs.calendar.navigate(1);
|
|
492
|
+
this.$refs.calendar.goToDate(new Date('2024-12-25'));
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
</script>
|
|
497
|
+
```
|
|
731
498
|
|
|
732
|
-
###
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
499
|
+
### Angular
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
import { Component, ViewChild } from '@angular/core';
|
|
503
|
+
import { SimpleCalendarJsComponent } from 'simple-calendar-js/frameworks/simple-calendar-js-angular.component';
|
|
504
|
+
|
|
505
|
+
@Component({
|
|
506
|
+
selector: 'app-root',
|
|
507
|
+
template: `
|
|
508
|
+
<simple-calendar-js
|
|
509
|
+
#calendar
|
|
510
|
+
[defaultView]="'month'"
|
|
511
|
+
[fetchEvents]="fetchEvents"
|
|
512
|
+
(eventClick)="handleEventClick($event)"
|
|
513
|
+
(slotClick)="handleSlotClick($event)"
|
|
514
|
+
(viewChange)="handleViewChange($event)"
|
|
515
|
+
(navigate)="handleNavigate($event)"
|
|
516
|
+
></simple-calendar-js>
|
|
517
|
+
`
|
|
518
|
+
})
|
|
519
|
+
export class AppComponent {
|
|
520
|
+
@ViewChild('calendar') calendar!: SimpleCalendarJsComponent;
|
|
521
|
+
|
|
522
|
+
someAction() {
|
|
523
|
+
// Access imperative methods
|
|
524
|
+
this.calendar.goToToday();
|
|
525
|
+
this.calendar.setView('week');
|
|
526
|
+
this.calendar.navigate(1);
|
|
527
|
+
this.calendar.goToDate(new Date('2024-12-25'));
|
|
528
|
+
}
|
|
529
|
+
}
|
|
746
530
|
```
|
|
747
531
|
|
|
748
532
|
## Browser Support
|
|
@@ -752,25 +536,18 @@ const yellowEvent = {
|
|
|
752
536
|
- Safari 12+
|
|
753
537
|
- Edge 79+
|
|
754
538
|
|
|
755
|
-
## File Structure
|
|
756
|
-
|
|
757
|
-
```
|
|
758
|
-
simple-calendar-js/
|
|
759
|
-
├── css/
|
|
760
|
-
│ └── simple-calendar-js.css # Main stylesheet
|
|
761
|
-
├── js/
|
|
762
|
-
│ └── simple-calendar-js.js # Main JavaScript file
|
|
763
|
-
├── index.html # Demo page
|
|
764
|
-
├── README.md # This file
|
|
765
|
-
└── package.json # Package configuration
|
|
766
|
-
```
|
|
767
|
-
|
|
768
539
|
## License
|
|
769
540
|
|
|
770
|
-
|
|
541
|
+
This project is available for personal, educational, and non-commercial use.
|
|
542
|
+
|
|
543
|
+
**Commercial use requires a separate license.** See [LICENSE](LICENSE) file for full terms.
|
|
771
544
|
|
|
772
|
-
|
|
545
|
+
For commercial licensing inquiries: simplecalendarjs@gmail.com
|
|
773
546
|
|
|
774
|
-
|
|
547
|
+
## Links
|
|
775
548
|
|
|
776
|
-
|
|
549
|
+
- **Documentation**: [docs.html](docs.html)
|
|
550
|
+
- **Demo**: [index.html](index.html)
|
|
551
|
+
- **Repository**: [github.com/pclslopes/SimpleCalendarJs](https://github.com/pclslopes/SimpleCalendarJs)
|
|
552
|
+
- **NPM**: [npmjs.com/package/simple-calendar-js](https://www.npmjs.com/package/simple-calendar-js)
|
|
553
|
+
- **Website**: [simplecalendarjs.com](https://www.simplecalendarjs.com)
|