big-calendar 0.1.0
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/CUSTOMIZATION.md +822 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/big-calendar.cjs +2 -0
- package/dist/big-calendar.cjs.map +1 -0
- package/dist/big-calendar.mjs +2882 -0
- package/dist/big-calendar.mjs.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +101 -0
package/CUSTOMIZATION.md
ADDED
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
# Calendar Customization Guide
|
|
2
|
+
|
|
3
|
+
This calendar package is highly customizable. You can control API connectivity, visibility of UI elements, settings, and more without modifying the UI appearance.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [API Integration](#api-integration)
|
|
8
|
+
2. [Mock Data Toggle](#mock-data-toggle)
|
|
9
|
+
3. [Visibility Controls](#visibility-controls)
|
|
10
|
+
4. [Custom Settings](#custom-settings)
|
|
11
|
+
5. [Event Callbacks](#event-callbacks)
|
|
12
|
+
6. [Examples](#examples)
|
|
13
|
+
|
|
14
|
+
## API Integration
|
|
15
|
+
|
|
16
|
+
Connect the calendar to your backend API by providing API functions to the `CalendarProvider`.
|
|
17
|
+
|
|
18
|
+
### Basic Setup
|
|
19
|
+
|
|
20
|
+
```jsx
|
|
21
|
+
import { CalendarProvider, ClientContainer } from 'big-calendar';
|
|
22
|
+
|
|
23
|
+
const calendarAPI = {
|
|
24
|
+
getEvents: async () => {
|
|
25
|
+
const response = await fetch('/api/events');
|
|
26
|
+
return response.json();
|
|
27
|
+
},
|
|
28
|
+
getUsers: async () => {
|
|
29
|
+
const response = await fetch('/api/users');
|
|
30
|
+
return response.json();
|
|
31
|
+
},
|
|
32
|
+
createEvent: async (eventData) => {
|
|
33
|
+
const response = await fetch('/api/events', {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
body: JSON.stringify(eventData),
|
|
37
|
+
});
|
|
38
|
+
return response.json();
|
|
39
|
+
},
|
|
40
|
+
updateEvent: async (eventData) => {
|
|
41
|
+
const response = await fetch(`/api/events/${eventData.id}`, {
|
|
42
|
+
method: 'PUT',
|
|
43
|
+
headers: { 'Content-Type': 'application/json' },
|
|
44
|
+
body: JSON.stringify(eventData),
|
|
45
|
+
});
|
|
46
|
+
return response.json();
|
|
47
|
+
},
|
|
48
|
+
deleteEvent: async (eventId) => {
|
|
49
|
+
await fetch(`/api/events/${eventId}`, { method: 'DELETE' });
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function App() {
|
|
54
|
+
return (
|
|
55
|
+
<CalendarProvider api={calendarAPI}>
|
|
56
|
+
<ClientContainer view="month" onViewChange={(view) => console.log(view)} />
|
|
57
|
+
</CalendarProvider>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Third-Party Calendar Integrations
|
|
63
|
+
|
|
64
|
+
You can integrate with Google Calendar, Outlook, or any other calendar service:
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
// Google Calendar integration example
|
|
68
|
+
const googleCalendarAPI = {
|
|
69
|
+
getEvents: async () => {
|
|
70
|
+
const response = await gapi.client.calendar.events.list({
|
|
71
|
+
calendarId: 'primary',
|
|
72
|
+
timeMin: new Date().toISOString(),
|
|
73
|
+
});
|
|
74
|
+
return response.result.items.map(transformGoogleEvent);
|
|
75
|
+
},
|
|
76
|
+
createEvent: async (eventData) => {
|
|
77
|
+
const response = await gapi.client.calendar.events.insert({
|
|
78
|
+
calendarId: 'primary',
|
|
79
|
+
resource: transformToGoogleEvent(eventData),
|
|
80
|
+
});
|
|
81
|
+
return transformGoogleEvent(response.result);
|
|
82
|
+
},
|
|
83
|
+
// ... other methods
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Mock Data Toggle
|
|
88
|
+
|
|
89
|
+
Use mock data for development or when API is not available:
|
|
90
|
+
|
|
91
|
+
```jsx
|
|
92
|
+
// Use mocks (default behavior when no API provided)
|
|
93
|
+
<CalendarProvider useMocks={true}>
|
|
94
|
+
<ClientContainer view="month" />
|
|
95
|
+
</CalendarProvider>
|
|
96
|
+
|
|
97
|
+
// Or provide initial data
|
|
98
|
+
<CalendarProvider
|
|
99
|
+
users={myUsers}
|
|
100
|
+
events={myEvents}
|
|
101
|
+
useMocks={false}
|
|
102
|
+
>
|
|
103
|
+
<ClientContainer view="month" />
|
|
104
|
+
</CalendarProvider>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Visibility Controls
|
|
108
|
+
|
|
109
|
+
Hide or show specific UI elements without changing the appearance:
|
|
110
|
+
|
|
111
|
+
### Hide Entire Header
|
|
112
|
+
|
|
113
|
+
```jsx
|
|
114
|
+
<ClientContainer
|
|
115
|
+
view="month"
|
|
116
|
+
showHeader={false}
|
|
117
|
+
/>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Customize Header Elements
|
|
121
|
+
|
|
122
|
+
```jsx
|
|
123
|
+
<ClientContainer
|
|
124
|
+
view="month"
|
|
125
|
+
headerProps={{
|
|
126
|
+
showTodayButton: true, // Show/hide today button
|
|
127
|
+
showDateNavigator: true, // Show/hide date navigator
|
|
128
|
+
showViewSwitcher: true, // Show/hide view buttons
|
|
129
|
+
showUserSelect: true, // Show/hide user filter
|
|
130
|
+
showAddEventButton: true, // Show/hide add event button
|
|
131
|
+
availableViews: ['day', 'week', 'month'], // Limit available views
|
|
132
|
+
}}
|
|
133
|
+
/>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Custom Settings
|
|
137
|
+
|
|
138
|
+
Configure default calendar settings:
|
|
139
|
+
|
|
140
|
+
```jsx
|
|
141
|
+
const customSettings = {
|
|
142
|
+
badgeVariant: 'colored', // 'colored' | 'outline' | 'default'
|
|
143
|
+
visibleHours: { from: 7, to: 18 },
|
|
144
|
+
workingHours: {
|
|
145
|
+
0: { from: 0, to: 0 }, // Sunday
|
|
146
|
+
1: { from: 8, to: 17 }, // Monday
|
|
147
|
+
2: { from: 8, to: 17 }, // Tuesday
|
|
148
|
+
3: { from: 8, to: 17 }, // Wednesday
|
|
149
|
+
4: { from: 8, to: 17 }, // Thursday
|
|
150
|
+
5: { from: 8, to: 17 }, // Friday
|
|
151
|
+
6: { from: 8, to: 12 }, // Saturday
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
<CalendarProvider
|
|
156
|
+
defaultSettings={customSettings}
|
|
157
|
+
onSettingsChange={(settings) => {
|
|
158
|
+
// Sync settings to your backend
|
|
159
|
+
console.log('Settings changed:', settings);
|
|
160
|
+
}}
|
|
161
|
+
>
|
|
162
|
+
<ClientContainer view="month" />
|
|
163
|
+
</CalendarProvider>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Event Callbacks
|
|
167
|
+
|
|
168
|
+
Listen to calendar events for additional functionality:
|
|
169
|
+
|
|
170
|
+
```jsx
|
|
171
|
+
<CalendarProvider
|
|
172
|
+
api={calendarAPI}
|
|
173
|
+
onEventCreate={(event) => {
|
|
174
|
+
console.log('Event created:', event);
|
|
175
|
+
// Trigger notifications, analytics, etc.
|
|
176
|
+
}}
|
|
177
|
+
onEventUpdate={(event) => {
|
|
178
|
+
console.log('Event updated:', event);
|
|
179
|
+
// Sync to other systems, update cache, etc.
|
|
180
|
+
}}
|
|
181
|
+
onEventDelete={(eventId) => {
|
|
182
|
+
console.log('Event deleted:', eventId);
|
|
183
|
+
// Clean up related data, etc.
|
|
184
|
+
}}
|
|
185
|
+
onSettingsChange={(settings) => {
|
|
186
|
+
console.log('Settings changed:', settings);
|
|
187
|
+
// Persist to localStorage or backend
|
|
188
|
+
}}
|
|
189
|
+
>
|
|
190
|
+
<ClientContainer view="month" />
|
|
191
|
+
</CalendarProvider>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Examples
|
|
195
|
+
|
|
196
|
+
### Complete Example with API Integration
|
|
197
|
+
|
|
198
|
+
```jsx
|
|
199
|
+
import { CalendarProvider, ClientContainer } from 'big-calendar';
|
|
200
|
+
import { useState } from 'react';
|
|
201
|
+
|
|
202
|
+
function MyCalendar() {
|
|
203
|
+
const [view, setView] = useState('month');
|
|
204
|
+
|
|
205
|
+
const calendarAPI = {
|
|
206
|
+
getEvents: async () => {
|
|
207
|
+
const response = await fetch('/api/events');
|
|
208
|
+
if (!response.ok) throw new Error('Failed to fetch events');
|
|
209
|
+
return response.json();
|
|
210
|
+
},
|
|
211
|
+
getUsers: async () => {
|
|
212
|
+
const response = await fetch('/api/users');
|
|
213
|
+
if (!response.ok) throw new Error('Failed to fetch users');
|
|
214
|
+
return response.json();
|
|
215
|
+
},
|
|
216
|
+
createEvent: async (eventData) => {
|
|
217
|
+
const response = await fetch('/api/events', {
|
|
218
|
+
method: 'POST',
|
|
219
|
+
headers: { 'Content-Type': 'application/json' },
|
|
220
|
+
body: JSON.stringify(eventData),
|
|
221
|
+
});
|
|
222
|
+
if (!response.ok) throw new Error('Failed to create event');
|
|
223
|
+
return response.json();
|
|
224
|
+
},
|
|
225
|
+
updateEvent: async (eventData) => {
|
|
226
|
+
const response = await fetch(`/api/events/${eventData.id}`, {
|
|
227
|
+
method: 'PUT',
|
|
228
|
+
headers: { 'Content-Type': 'application/json' },
|
|
229
|
+
body: JSON.stringify(eventData),
|
|
230
|
+
});
|
|
231
|
+
if (!response.ok) throw new Error('Failed to update event');
|
|
232
|
+
return response.json();
|
|
233
|
+
},
|
|
234
|
+
deleteEvent: async (eventId) => {
|
|
235
|
+
const response = await fetch(`/api/events/${eventId}`, {
|
|
236
|
+
method: 'DELETE',
|
|
237
|
+
});
|
|
238
|
+
if (!response.ok) throw new Error('Failed to delete event');
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
<CalendarProvider
|
|
244
|
+
api={calendarAPI}
|
|
245
|
+
defaultSettings={{
|
|
246
|
+
badgeVariant: 'colored',
|
|
247
|
+
visibleHours: { from: 8, to: 20 },
|
|
248
|
+
}}
|
|
249
|
+
onEventCreate={(event) => {
|
|
250
|
+
// Show success notification
|
|
251
|
+
toast.success('Event created successfully!');
|
|
252
|
+
}}
|
|
253
|
+
>
|
|
254
|
+
<ClientContainer
|
|
255
|
+
view={view}
|
|
256
|
+
onViewChange={setView}
|
|
257
|
+
showHeader={true}
|
|
258
|
+
headerProps={{
|
|
259
|
+
showAddEventButton: true,
|
|
260
|
+
availableViews: ['day', 'week', 'month'],
|
|
261
|
+
}}
|
|
262
|
+
/>
|
|
263
|
+
</CalendarProvider>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Minimal Example (Using Mocks)
|
|
269
|
+
|
|
270
|
+
```jsx
|
|
271
|
+
import { CalendarProvider, ClientContainer } from 'big-calendar';
|
|
272
|
+
|
|
273
|
+
function SimpleCalendar() {
|
|
274
|
+
return (
|
|
275
|
+
<CalendarProvider useMocks={true}>
|
|
276
|
+
<ClientContainer view="month" />
|
|
277
|
+
</CalendarProvider>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Custom Header Configuration
|
|
283
|
+
|
|
284
|
+
```jsx
|
|
285
|
+
<ClientContainer
|
|
286
|
+
view="month"
|
|
287
|
+
headerProps={{
|
|
288
|
+
showTodayButton: false, // Hide today button
|
|
289
|
+
showDateNavigator: true, // Keep date navigator
|
|
290
|
+
showViewSwitcher: true, // Keep view switcher
|
|
291
|
+
showUserSelect: false, // Hide user filter
|
|
292
|
+
showAddEventButton: true, // Keep add button
|
|
293
|
+
availableViews: ['week', 'month'], // Only show week and month views
|
|
294
|
+
}}
|
|
295
|
+
/>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## API Function Signatures
|
|
299
|
+
|
|
300
|
+
All API functions are optional. If not provided, the calendar will use mock data or local state.
|
|
301
|
+
|
|
302
|
+
### `getEvents(): Promise<CalendarEvent[]>`
|
|
303
|
+
Fetches all events. Should return an array of event objects.
|
|
304
|
+
|
|
305
|
+
### `getUsers(): Promise<CalendarUser[]>`
|
|
306
|
+
Fetches all users. Should return an array of user objects.
|
|
307
|
+
|
|
308
|
+
### `createEvent(eventData): Promise<CalendarEvent>`
|
|
309
|
+
Creates a new event. Receives event data (without id) and should return the created event with id.
|
|
310
|
+
|
|
311
|
+
### `updateEvent(eventData): Promise<CalendarEvent>`
|
|
312
|
+
Updates an existing event. Receives complete event data and should return the updated event.
|
|
313
|
+
|
|
314
|
+
### `deleteEvent(eventId): Promise<void>`
|
|
315
|
+
Deletes an event by ID. Should return void or a promise that resolves to void.
|
|
316
|
+
|
|
317
|
+
## Event Data Structure
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
interface CalendarEvent {
|
|
321
|
+
id: string | number;
|
|
322
|
+
startDate: string; // ISO string
|
|
323
|
+
endDate: string; // ISO string
|
|
324
|
+
title: string;
|
|
325
|
+
description: string;
|
|
326
|
+
color: 'blue' | 'green' | 'red' | 'yellow' | 'purple' | 'orange' | 'gray';
|
|
327
|
+
user: {
|
|
328
|
+
id: string;
|
|
329
|
+
name: string;
|
|
330
|
+
picturePath?: string | null;
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Styling Customization
|
|
336
|
+
|
|
337
|
+
The calendar is fully customizable for styling without affecting the default UI appearance. You can customize colors, spacing, borders, typography, and layout through CSS variables and className props.
|
|
338
|
+
|
|
339
|
+
### CSS Variables
|
|
340
|
+
|
|
341
|
+
Override CSS variables in your application's CSS to customize the calendar appearance:
|
|
342
|
+
|
|
343
|
+
```css
|
|
344
|
+
:root {
|
|
345
|
+
/* Color customization (already supported) */
|
|
346
|
+
--background: 0 0% 100%;
|
|
347
|
+
--foreground: 240 10% 3.9%;
|
|
348
|
+
--primary: 240 5.9% 10%;
|
|
349
|
+
--border: 240 5.9% 90%;
|
|
350
|
+
--radius: 0.5rem;
|
|
351
|
+
|
|
352
|
+
/* Calendar-specific spacing and layout */
|
|
353
|
+
--calendar-container-border-radius: 0.75rem; /* rounded-xl */
|
|
354
|
+
--calendar-container-padding: 0;
|
|
355
|
+
--calendar-header-padding: 1rem; /* p-4 */
|
|
356
|
+
--calendar-header-gap: 1rem; /* gap-4 */
|
|
357
|
+
--calendar-header-border-width: 1px;
|
|
358
|
+
--calendar-spacing-xs: 0.25rem; /* gap-1 */
|
|
359
|
+
--calendar-spacing-sm: 0.5rem; /* gap-2 */
|
|
360
|
+
--calendar-spacing-md: 0.75rem; /* gap-3 */
|
|
361
|
+
--calendar-spacing-lg: 1rem; /* gap-4 */
|
|
362
|
+
--calendar-spacing-xl: 1.5rem; /* gap-6 */
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.dark {
|
|
366
|
+
/* Override for dark mode */
|
|
367
|
+
--calendar-container-border-radius: 0.75rem;
|
|
368
|
+
--calendar-header-padding: 1rem;
|
|
369
|
+
/* ... other variables */
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### className Props
|
|
374
|
+
|
|
375
|
+
Add custom classes to override or extend component styles:
|
|
376
|
+
|
|
377
|
+
```jsx
|
|
378
|
+
<ClientContainer
|
|
379
|
+
view="month"
|
|
380
|
+
className="my-custom-calendar" // Custom container styles
|
|
381
|
+
headerClassName="custom-header" // Custom header styles
|
|
382
|
+
contentClassName="custom-content" // Custom content area styles
|
|
383
|
+
headerProps={{
|
|
384
|
+
className: "additional-header-class",
|
|
385
|
+
leftSectionClassName: "custom-left-section",
|
|
386
|
+
rightSectionClassName: "custom-right-section",
|
|
387
|
+
viewSwitcherClassName: "custom-view-switcher",
|
|
388
|
+
addButtonClassName: "custom-add-button",
|
|
389
|
+
}}
|
|
390
|
+
/>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### CSS Override Examples
|
|
394
|
+
|
|
395
|
+
#### Custom Border Radius
|
|
396
|
+
|
|
397
|
+
```css
|
|
398
|
+
/* Make calendar container square */
|
|
399
|
+
:root {
|
|
400
|
+
--calendar-container-border-radius: 0;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* Or override with className */
|
|
404
|
+
.my-calendar {
|
|
405
|
+
border-radius: 0 !important;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### Custom Spacing
|
|
410
|
+
|
|
411
|
+
```css
|
|
412
|
+
/* Increase header padding */
|
|
413
|
+
:root {
|
|
414
|
+
--calendar-header-padding: 1.5rem;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Or use className */
|
|
418
|
+
.custom-header {
|
|
419
|
+
padding: 1.5rem !important;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
#### Custom Colors
|
|
424
|
+
|
|
425
|
+
```css
|
|
426
|
+
/* Change calendar border color */
|
|
427
|
+
:root {
|
|
428
|
+
--border: 220 13% 91%; /* Custom border color */
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/* Change primary color */
|
|
432
|
+
:root {
|
|
433
|
+
--primary: 221 83% 53%; /* Blue primary */
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### Custom Layout
|
|
438
|
+
|
|
439
|
+
```jsx
|
|
440
|
+
// Remove border radius
|
|
441
|
+
<ClientContainer
|
|
442
|
+
view="month"
|
|
443
|
+
className="rounded-none"
|
|
444
|
+
/>
|
|
445
|
+
|
|
446
|
+
// Add custom shadow
|
|
447
|
+
<ClientContainer
|
|
448
|
+
view="month"
|
|
449
|
+
className="shadow-2xl"
|
|
450
|
+
/>
|
|
451
|
+
|
|
452
|
+
// Custom header styling
|
|
453
|
+
<ClientContainer
|
|
454
|
+
view="month"
|
|
455
|
+
headerProps={{
|
|
456
|
+
className: "bg-gradient-to-r from-blue-500 to-purple-500 text-white",
|
|
457
|
+
}}
|
|
458
|
+
/>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Tailwind Class Overrides
|
|
462
|
+
|
|
463
|
+
Since the calendar uses Tailwind CSS, you can override classes using Tailwind's specificity:
|
|
464
|
+
|
|
465
|
+
```css
|
|
466
|
+
/* Override specific calendar classes */
|
|
467
|
+
.big-calendar-container {
|
|
468
|
+
border-radius: 0.5rem; /* Override rounded-xl */
|
|
469
|
+
padding: 1rem; /* Add padding */
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.big-calendar-header {
|
|
473
|
+
background: linear-gradient(to right, #3b82f6, #8b5cf6);
|
|
474
|
+
color: white;
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Complete Styling Example
|
|
479
|
+
|
|
480
|
+
```jsx
|
|
481
|
+
import { CalendarProvider, ClientContainer } from 'big-calendar';
|
|
482
|
+
import './custom-calendar-styles.css'; // Your custom CSS
|
|
483
|
+
|
|
484
|
+
function MyStyledCalendar() {
|
|
485
|
+
return (
|
|
486
|
+
<CalendarProvider useMocks={true}>
|
|
487
|
+
<ClientContainer
|
|
488
|
+
view="month"
|
|
489
|
+
className="my-custom-calendar shadow-lg"
|
|
490
|
+
headerClassName="bg-blue-50 border-blue-200"
|
|
491
|
+
contentClassName="p-2"
|
|
492
|
+
headerProps={{
|
|
493
|
+
leftSectionClassName: "gap-4",
|
|
494
|
+
rightSectionClassName: "gap-2",
|
|
495
|
+
addButtonClassName: "bg-blue-600 hover:bg-blue-700",
|
|
496
|
+
}}
|
|
497
|
+
/>
|
|
498
|
+
</CalendarProvider>
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
```css
|
|
504
|
+
/* custom-calendar-styles.css */
|
|
505
|
+
:root {
|
|
506
|
+
/* Container and header */
|
|
507
|
+
--calendar-container-border-radius: 1rem;
|
|
508
|
+
--calendar-header-padding: 1.25rem;
|
|
509
|
+
--calendar-spacing-lg: 1.25rem;
|
|
510
|
+
|
|
511
|
+
/* Event cards */
|
|
512
|
+
--calendar-event-border-radius: 0.5rem;
|
|
513
|
+
--calendar-event-border-width: 2px;
|
|
514
|
+
--calendar-event-padding-x: 0.75rem;
|
|
515
|
+
--calendar-event-padding-y: 0.5rem;
|
|
516
|
+
|
|
517
|
+
/* Custom event colors */
|
|
518
|
+
--calendar-event-blue-border: 217 91% 50%;
|
|
519
|
+
--calendar-event-blue-bg: 217 91% 98%;
|
|
520
|
+
--calendar-event-blue-text: 217 91% 25%;
|
|
521
|
+
|
|
522
|
+
--calendar-event-red-border: 0 84% 55%;
|
|
523
|
+
--calendar-event-red-bg: 0 84% 97%;
|
|
524
|
+
--calendar-event-red-text: 0 84% 25%;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.my-custom-calendar {
|
|
528
|
+
border: 2px solid #e5e7eb;
|
|
529
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/* Override specific event styles */
|
|
533
|
+
.my-custom-calendar [class*="border-blue"] {
|
|
534
|
+
border-radius: 0.75rem;
|
|
535
|
+
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.2);
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Event-Specific Styling Examples
|
|
540
|
+
|
|
541
|
+
#### Custom Event Border Radius
|
|
542
|
+
|
|
543
|
+
```css
|
|
544
|
+
/* Make all events rounded */
|
|
545
|
+
:root {
|
|
546
|
+
--calendar-event-border-radius: 1rem; /* Fully rounded */
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/* Or target specific views */
|
|
550
|
+
.calendar-month-view [class*="event"] {
|
|
551
|
+
border-radius: 0.25rem; /* Less rounded in month view */
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.calendar-week-view [class*="event"] {
|
|
555
|
+
border-radius: 0.75rem; /* More rounded in week view */
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
#### Custom Event Colors
|
|
560
|
+
|
|
561
|
+
```css
|
|
562
|
+
/* Change all blue events to purple */
|
|
563
|
+
.border-blue-200 {
|
|
564
|
+
border-color: hsl(262, 83%, 58%) !important;
|
|
565
|
+
background-color: hsl(262, 83%, 95%) !important;
|
|
566
|
+
color: hsl(262, 83%, 30%) !important;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/* Make red events more vibrant */
|
|
570
|
+
.border-red-200 {
|
|
571
|
+
border-color: hsl(0, 100%, 50%) !important;
|
|
572
|
+
background-color: hsl(0, 100%, 97%) !important;
|
|
573
|
+
color: hsl(0, 100%, 20%) !important;
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
#### Custom Event Borders
|
|
578
|
+
|
|
579
|
+
```css
|
|
580
|
+
/* Thicker borders for all events */
|
|
581
|
+
:root {
|
|
582
|
+
--calendar-event-border-width: 2px;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/* Dashed borders */
|
|
586
|
+
[class*="border-blue-200"],
|
|
587
|
+
[class*="border-green-200"],
|
|
588
|
+
[class*="border-red-200"] {
|
|
589
|
+
border-style: dashed !important;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/* No borders */
|
|
593
|
+
[class*="event"] {
|
|
594
|
+
border-width: 0 !important;
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### Styling Best Practices
|
|
599
|
+
|
|
600
|
+
1. **Use CSS Variables** for theme-wide changes (colors, spacing, borders)
|
|
601
|
+
2. **Use className Props** for component-specific overrides
|
|
602
|
+
3. **Use Tailwind Classes** for quick utility-based styling
|
|
603
|
+
4. **Combine Approaches** - Use CSS variables for defaults and className for specific instances
|
|
604
|
+
5. **Maintain Specificity** - Use `!important` sparingly, prefer higher specificity selectors
|
|
605
|
+
|
|
606
|
+
### Event Card Customization
|
|
607
|
+
|
|
608
|
+
Customize event cards (colors, borders, radiuses) through CSS variables and className props:
|
|
609
|
+
|
|
610
|
+
#### Event Colors
|
|
611
|
+
|
|
612
|
+
Override event colors using CSS variables:
|
|
613
|
+
|
|
614
|
+
```css
|
|
615
|
+
:root {
|
|
616
|
+
/* Blue event colors */
|
|
617
|
+
--calendar-event-blue-border: 217 91% 60%;
|
|
618
|
+
--calendar-event-blue-bg: 217 91% 95%;
|
|
619
|
+
--calendar-event-blue-text: 217 91% 30%;
|
|
620
|
+
|
|
621
|
+
/* Green event colors */
|
|
622
|
+
--calendar-event-green-border: 142 71% 45%;
|
|
623
|
+
--calendar-event-green-bg: 142 71% 95%;
|
|
624
|
+
--calendar-event-green-text: 142 71% 25%;
|
|
625
|
+
|
|
626
|
+
/* Red event colors */
|
|
627
|
+
--calendar-event-red-border: 0 84% 60%;
|
|
628
|
+
--calendar-event-red-bg: 0 84% 95%;
|
|
629
|
+
--calendar-event-red-text: 0 84% 30%;
|
|
630
|
+
|
|
631
|
+
/* Customize all colors similarly */
|
|
632
|
+
--calendar-event-yellow-border: 43 96% 56%;
|
|
633
|
+
--calendar-event-purple-border: 262 83% 58%;
|
|
634
|
+
--calendar-event-orange-border: 25 95% 53%;
|
|
635
|
+
--calendar-event-gray-border: 0 0% 90%;
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
#### Event Border Radius and Spacing
|
|
640
|
+
|
|
641
|
+
```css
|
|
642
|
+
:root {
|
|
643
|
+
--calendar-event-border-radius: 0.5rem; /* Change from default 0.375rem */
|
|
644
|
+
--calendar-event-border-width: 2px; /* Thicker borders */
|
|
645
|
+
--calendar-event-padding-x: 0.75rem; /* More horizontal padding */
|
|
646
|
+
--calendar-event-padding-y: 0.5rem; /* More vertical padding */
|
|
647
|
+
--calendar-event-gap: 0.25rem; /* More gap between elements */
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
#### Override Event Styles with CSS
|
|
652
|
+
|
|
653
|
+
```css
|
|
654
|
+
/* Target all event cards */
|
|
655
|
+
[class*="event"] {
|
|
656
|
+
border-radius: 0.5rem !important;
|
|
657
|
+
border-width: 2px !important;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/* Target specific event colors */
|
|
661
|
+
.border-blue-200 {
|
|
662
|
+
border-color: #your-custom-blue !important;
|
|
663
|
+
background-color: #your-custom-bg !important;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/* Target event cards in specific views */
|
|
667
|
+
.calendar-month-view [class*="event"] {
|
|
668
|
+
border-radius: 0.25rem;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
.calendar-week-view [class*="event"] {
|
|
672
|
+
border-radius: 0.5rem;
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
#### Override Event Colors Completely
|
|
677
|
+
|
|
678
|
+
```css
|
|
679
|
+
/* Replace all blue events with custom color */
|
|
680
|
+
.border-blue-200 {
|
|
681
|
+
border-color: hsl(280, 70%, 50%) !important;
|
|
682
|
+
background-color: hsl(280, 70%, 95%) !important;
|
|
683
|
+
color: hsl(280, 70%, 20%) !important;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/* Dark mode overrides */
|
|
687
|
+
.dark .border-blue-200 {
|
|
688
|
+
border-color: hsl(280, 70%, 40%) !important;
|
|
689
|
+
background-color: hsl(280, 70%, 10%) !important;
|
|
690
|
+
color: hsl(280, 70%, 85%) !important;
|
|
691
|
+
}
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Available CSS Variables
|
|
695
|
+
|
|
696
|
+
| Variable | Default | Description |
|
|
697
|
+
|----------|---------|-------------|
|
|
698
|
+
| `--calendar-container-border-radius` | `0.75rem` | Container border radius |
|
|
699
|
+
| `--calendar-container-padding` | `0` | Container padding |
|
|
700
|
+
| `--calendar-header-padding` | `1rem` | Header padding |
|
|
701
|
+
| `--calendar-header-gap` | `1rem` | Header gap spacing |
|
|
702
|
+
| `--calendar-header-border-width` | `1px` | Header border width |
|
|
703
|
+
| `--calendar-spacing-xs` | `0.25rem` | Extra small spacing |
|
|
704
|
+
| `--calendar-spacing-sm` | `0.5rem` | Small spacing |
|
|
705
|
+
| `--calendar-spacing-md` | `0.75rem` | Medium spacing |
|
|
706
|
+
| `--calendar-spacing-lg` | `1rem` | Large spacing |
|
|
707
|
+
| `--calendar-spacing-xl` | `1.5rem` | Extra large spacing |
|
|
708
|
+
| `--calendar-event-border-radius` | `0.375rem` | Event card border radius |
|
|
709
|
+
| `--calendar-event-border-width` | `1px` | Event card border width |
|
|
710
|
+
| `--calendar-event-padding-x` | `0.5rem` | Event card horizontal padding |
|
|
711
|
+
| `--calendar-event-padding-y` | `0.375rem` | Event card vertical padding |
|
|
712
|
+
| `--calendar-event-gap` | `0.125rem` | Event card internal gap |
|
|
713
|
+
| `--calendar-event-{color}-border` | Various | Event border color (HSL) |
|
|
714
|
+
| `--calendar-event-{color}-bg` | Various | Event background color (HSL) |
|
|
715
|
+
| `--calendar-event-{color}-text` | Various | Event text color (HSL) |
|
|
716
|
+
|
|
717
|
+
**Event Color Variables** (replace `{color}` with: `blue`, `green`, `red`, `yellow`, `purple`, `orange`, `gray`):
|
|
718
|
+
- `--calendar-event-{color}-border`
|
|
719
|
+
- `--calendar-event-{color}-bg`
|
|
720
|
+
- `--calendar-event-{color}-text`
|
|
721
|
+
|
|
722
|
+
## Single-User Mode
|
|
723
|
+
|
|
724
|
+
For single-user applications, enable single-user mode to hide user selection UI and simplify forms:
|
|
725
|
+
|
|
726
|
+
```jsx
|
|
727
|
+
<CalendarProvider
|
|
728
|
+
singleUser={true}
|
|
729
|
+
currentUser={{
|
|
730
|
+
id: "user-123",
|
|
731
|
+
name: "John Doe",
|
|
732
|
+
picturePath: "/avatar.jpg",
|
|
733
|
+
}}
|
|
734
|
+
useMocks={true}
|
|
735
|
+
>
|
|
736
|
+
<ClientContainer view="month" />
|
|
737
|
+
</CalendarProvider>
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
### Single-User Features
|
|
741
|
+
|
|
742
|
+
- **Hides user select** in calendar header automatically
|
|
743
|
+
- **Removes user field** from add/edit event forms
|
|
744
|
+
- **Uses currentUser** automatically for all events
|
|
745
|
+
- **Simplifies forms** - no user selection needed
|
|
746
|
+
|
|
747
|
+
### Single-User Example
|
|
748
|
+
|
|
749
|
+
```jsx
|
|
750
|
+
import { CalendarProvider, ClientContainer } from 'big-calendar';
|
|
751
|
+
|
|
752
|
+
function SingleUserCalendar() {
|
|
753
|
+
const currentUser = {
|
|
754
|
+
id: "user-123",
|
|
755
|
+
name: "John Doe",
|
|
756
|
+
picturePath: "/avatar.jpg",
|
|
757
|
+
};
|
|
758
|
+
|
|
759
|
+
return (
|
|
760
|
+
<CalendarProvider
|
|
761
|
+
singleUser={true}
|
|
762
|
+
currentUser={currentUser}
|
|
763
|
+
api={{
|
|
764
|
+
getEvents: async () => {
|
|
765
|
+
// Fetch events for currentUser only
|
|
766
|
+
const response = await fetch(`/api/users/${currentUser.id}/events`);
|
|
767
|
+
return response.json();
|
|
768
|
+
},
|
|
769
|
+
createEvent: async (eventData) => {
|
|
770
|
+
// Automatically includes currentUser
|
|
771
|
+
const response = await fetch('/api/events', {
|
|
772
|
+
method: 'POST',
|
|
773
|
+
headers: { 'Content-Type': 'application/json' },
|
|
774
|
+
body: JSON.stringify({
|
|
775
|
+
...eventData,
|
|
776
|
+
userId: currentUser.id,
|
|
777
|
+
}),
|
|
778
|
+
});
|
|
779
|
+
return response.json();
|
|
780
|
+
},
|
|
781
|
+
}}
|
|
782
|
+
>
|
|
783
|
+
<ClientContainer view="month" />
|
|
784
|
+
</CalendarProvider>
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
## Form Disclaimer Toggle
|
|
790
|
+
|
|
791
|
+
Hide form disclaimers/descriptions in dialogs:
|
|
792
|
+
|
|
793
|
+
```jsx
|
|
794
|
+
<AddEventDialog showFormDisclaimer={false}>
|
|
795
|
+
<Button>Add Event</Button>
|
|
796
|
+
</AddEventDialog>
|
|
797
|
+
|
|
798
|
+
<EditEventDialog event={event} showFormDisclaimer={false}>
|
|
799
|
+
<Button>Edit</Button>
|
|
800
|
+
</EditEventDialog>
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Or disable globally by wrapping dialogs:
|
|
804
|
+
|
|
805
|
+
```jsx
|
|
806
|
+
// In your custom AddEventDialog wrapper
|
|
807
|
+
function CustomAddEventDialog(props) {
|
|
808
|
+
return <AddEventDialog {...props} showFormDisclaimer={false} />;
|
|
809
|
+
}
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
## Notes
|
|
813
|
+
|
|
814
|
+
- All customization options are optional and have sensible defaults
|
|
815
|
+
- The UI appearance remains unchanged by default - only functionality is customized
|
|
816
|
+
- Styling customization does not affect functionality - all features work the same
|
|
817
|
+
- API functions can be async and should handle errors appropriately
|
|
818
|
+
- The calendar will fall back to mock data if API functions fail and `useMocks` is true
|
|
819
|
+
- Settings can be changed programmatically through the context or via the provided UI components
|
|
820
|
+
- CSS variables and className props can be combined for maximum flexibility
|
|
821
|
+
- Single-user mode automatically hides user selection UI and simplifies forms
|
|
822
|
+
- In single-user mode, `currentUser` is automatically used for all events
|