kalendly 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/LICENSE +21 -0
- package/README.md +492 -0
- package/dist/core/index.d.mts +181 -0
- package/dist/core/index.d.ts +181 -0
- package/dist/core/index.js +349 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +309 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/index.d.mts +623 -0
- package/dist/index.d.ts +623 -0
- package/dist/index.js +1445 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1403 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +208 -0
- package/dist/react/index.d.ts +208 -0
- package/dist/react/index.js +558 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +516 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/react-native/index.d.mts +465 -0
- package/dist/react-native/index.d.ts +465 -0
- package/dist/react-native/index.js +894 -0
- package/dist/react-native/index.js.map +1 -0
- package/dist/react-native/index.mjs +851 -0
- package/dist/react-native/index.mjs.map +1 -0
- package/dist/styles/calendar.css +500 -0
- package/dist/vanilla/index.d.mts +214 -0
- package/dist/vanilla/index.d.ts +214 -0
- package/dist/vanilla/index.js +621 -0
- package/dist/vanilla/index.js.map +1 -0
- package/dist/vanilla/index.mjs +579 -0
- package/dist/vanilla/index.mjs.map +1 -0
- package/dist/vanilla/index.umd.js +604 -0
- package/dist/vanilla/index.umd.js.map +1 -0
- package/dist/vue/index.js +1 -0
- package/dist/vue/index.mjs +439 -0
- package/package.json +161 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Barestripe
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
# kalendly Universal Calendar Scheduler
|
|
2
|
+
|
|
3
|
+
A universal calendar scheduler component that works seamlessly across React, Vue, and React Native with full TypeScript support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Universal**: Works with React, Vue, React Native, and Vanilla JavaScript
|
|
8
|
+
- 📱 **Responsive**: Mobile-friendly design that matches your existing Vue implementation
|
|
9
|
+
- 🎨 **Customizable**: Easy to theme and customize with CSS variables
|
|
10
|
+
- 🔒 **Type Safe**: Full TypeScript support
|
|
11
|
+
- 📅 **Event Management**: Add, display, and manage events
|
|
12
|
+
- 🌐 **Accessible**: Built with accessibility in mind
|
|
13
|
+
- 📦 **Tree Shakeable**: Import only what you need
|
|
14
|
+
- 🎯 **Design Consistent**: Matches the original Vue calendar design and feel
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install kalendly
|
|
20
|
+
# or
|
|
21
|
+
yarn add kalendly
|
|
22
|
+
# or
|
|
23
|
+
pnpm add kalendly
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### React
|
|
29
|
+
|
|
30
|
+
```jsx
|
|
31
|
+
import React from 'react';
|
|
32
|
+
import { Calendar } from 'kalendly/react';
|
|
33
|
+
import 'kalendly/styles';
|
|
34
|
+
|
|
35
|
+
const events = [
|
|
36
|
+
{
|
|
37
|
+
id: 1,
|
|
38
|
+
name: 'Team Meeting',
|
|
39
|
+
date: '2025-01-15',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 2,
|
|
43
|
+
name: 'Project Deadline',
|
|
44
|
+
date: '2025-01-20',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
function App() {
|
|
49
|
+
const handleDateSelect = date => {
|
|
50
|
+
console.log('Selected date:', date);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div>
|
|
55
|
+
<Calendar
|
|
56
|
+
events={events}
|
|
57
|
+
onDateSelect={handleDateSelect}
|
|
58
|
+
title="My Calendar"
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default App;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Vue
|
|
68
|
+
|
|
69
|
+
```vue
|
|
70
|
+
<template>
|
|
71
|
+
<div>
|
|
72
|
+
<Calendar
|
|
73
|
+
:events="events"
|
|
74
|
+
@date-select="handleDateSelect"
|
|
75
|
+
title="My Calendar"
|
|
76
|
+
>
|
|
77
|
+
<template #event="{ event }">
|
|
78
|
+
<div class="custom-event">{{ event.name }}</div>
|
|
79
|
+
</template>
|
|
80
|
+
</Calendar>
|
|
81
|
+
</div>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<script setup>
|
|
85
|
+
import { Calendar } from 'kalendly/vue';
|
|
86
|
+
import 'kalendly/styles';
|
|
87
|
+
|
|
88
|
+
const events = [
|
|
89
|
+
{
|
|
90
|
+
id: 1,
|
|
91
|
+
name: 'Team Meeting',
|
|
92
|
+
date: '2025-01-15',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: 2,
|
|
96
|
+
name: 'Project Deadline',
|
|
97
|
+
date: '2025-01-20',
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const handleDateSelect = date => {
|
|
102
|
+
console.log('Selected date:', date);
|
|
103
|
+
};
|
|
104
|
+
</script>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### React Native
|
|
108
|
+
|
|
109
|
+
```jsx
|
|
110
|
+
import React from 'react';
|
|
111
|
+
import { View } from 'react-native';
|
|
112
|
+
import { Calendar } from 'kalendly/react-native';
|
|
113
|
+
|
|
114
|
+
const events = [
|
|
115
|
+
{
|
|
116
|
+
id: 1,
|
|
117
|
+
name: 'Team Meeting',
|
|
118
|
+
date: '2025-01-15',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: 2,
|
|
122
|
+
name: 'Project Deadline',
|
|
123
|
+
date: '2025-01-20',
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
function App() {
|
|
128
|
+
const handleDateSelect = date => {
|
|
129
|
+
console.log('Selected date:', date);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<View style={{ flex: 1 }}>
|
|
134
|
+
<Calendar
|
|
135
|
+
events={events}
|
|
136
|
+
onDateSelect={handleDateSelect}
|
|
137
|
+
title="My Calendar"
|
|
138
|
+
/>
|
|
139
|
+
</View>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export default App;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Vanilla JavaScript
|
|
147
|
+
|
|
148
|
+
#### Modern ES Modules (Recommended)
|
|
149
|
+
|
|
150
|
+
```html
|
|
151
|
+
<!DOCTYPE html>
|
|
152
|
+
<html>
|
|
153
|
+
<head>
|
|
154
|
+
<link
|
|
155
|
+
rel="stylesheet"
|
|
156
|
+
href="node_modules/kalendly/dist/styles/calendar.css"
|
|
157
|
+
/>
|
|
158
|
+
<title>Vanilla JS Calendar</title>
|
|
159
|
+
</head>
|
|
160
|
+
<body>
|
|
161
|
+
<div id="calendar"></div>
|
|
162
|
+
|
|
163
|
+
<script type="module">
|
|
164
|
+
import { createCalendar } from 'kalendly/vanilla';
|
|
165
|
+
|
|
166
|
+
const events = [
|
|
167
|
+
{ id: 1, name: 'Team Meeting', date: '2025-01-15' },
|
|
168
|
+
{ id: 2, name: 'Project Deadline', date: '2025-01-20' },
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
const calendar = createCalendar({
|
|
172
|
+
container: '#calendar',
|
|
173
|
+
events: events,
|
|
174
|
+
title: 'My Calendar',
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Listen to events (note: use addEventListener, not onclick)
|
|
178
|
+
document.getElementById('calendar').addEventListener('dateSelect', e => {
|
|
179
|
+
console.log('Selected date:', e.detail.date);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
document.getElementById('calendar').addEventListener('monthChange', e => {
|
|
183
|
+
console.log('Month changed:', e.detail.year, e.detail.month);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Update events dynamically
|
|
187
|
+
// calendar.updateEvents(newEvents);
|
|
188
|
+
|
|
189
|
+
// Navigate to specific date
|
|
190
|
+
// calendar.goToDate(new Date(2025, 5, 15));
|
|
191
|
+
|
|
192
|
+
// Cleanup when done
|
|
193
|
+
// calendar.destroy();
|
|
194
|
+
</script>
|
|
195
|
+
</body>
|
|
196
|
+
</html>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### CDN Usage (Browser)
|
|
200
|
+
|
|
201
|
+
```html
|
|
202
|
+
<!DOCTYPE html>
|
|
203
|
+
<html>
|
|
204
|
+
<head>
|
|
205
|
+
<link
|
|
206
|
+
rel="stylesheet"
|
|
207
|
+
href="https://unpkg.com/kalendly/dist/styles/calendar.css"
|
|
208
|
+
/>
|
|
209
|
+
</head>
|
|
210
|
+
<body>
|
|
211
|
+
<div id="calendar"></div>
|
|
212
|
+
|
|
213
|
+
<script type="module">
|
|
214
|
+
import { createCalendar } from 'https://unpkg.com/kalendly/dist/vanilla/index.mjs';
|
|
215
|
+
|
|
216
|
+
const calendar = createCalendar({
|
|
217
|
+
container: '#calendar',
|
|
218
|
+
events: [{ id: 1, name: 'Meeting', date: '2025-01-15' }],
|
|
219
|
+
title: 'My Calendar',
|
|
220
|
+
});
|
|
221
|
+
</script>
|
|
222
|
+
</body>
|
|
223
|
+
</html>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Legacy/Global Usage (Without Modules)
|
|
227
|
+
|
|
228
|
+
```html
|
|
229
|
+
<!DOCTYPE html>
|
|
230
|
+
<html>
|
|
231
|
+
<head>
|
|
232
|
+
<link
|
|
233
|
+
rel="stylesheet"
|
|
234
|
+
href="https://unpkg.com/kalendly/dist/styles/calendar.css"
|
|
235
|
+
/>
|
|
236
|
+
</head>
|
|
237
|
+
<body>
|
|
238
|
+
<div id="calendar"></div>
|
|
239
|
+
|
|
240
|
+
<script src="https://unpkg.com/kalendly/dist/vanilla/index.umd.js"></script>
|
|
241
|
+
<script>
|
|
242
|
+
const { createCalendar } = Kalendly;
|
|
243
|
+
|
|
244
|
+
const calendar = createCalendar({
|
|
245
|
+
container: '#calendar',
|
|
246
|
+
events: [{ id: 1, name: 'Meeting', date: '2025-01-15' }],
|
|
247
|
+
title: 'My Calendar',
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Now you can use global functions with onclick
|
|
251
|
+
function handleDateSelect() {
|
|
252
|
+
console.log('Date selected!');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
document
|
|
256
|
+
.getElementById('calendar')
|
|
257
|
+
.addEventListener('dateSelect', handleDateSelect);
|
|
258
|
+
</script>
|
|
259
|
+
</body>
|
|
260
|
+
</html>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## API Reference
|
|
264
|
+
|
|
265
|
+
### Props
|
|
266
|
+
|
|
267
|
+
| Prop | Type | Default | Description |
|
|
268
|
+
| --------------- | --------------------------------------- | ------------------ | --------------------------------------- |
|
|
269
|
+
| `events` | `CalendarEvent[]` | `[]` | Array of events to display |
|
|
270
|
+
| `initialDate` | `Date` | `new Date()` | Initial date to display |
|
|
271
|
+
| `minYear` | `number` | `currentYear - 30` | Minimum selectable year |
|
|
272
|
+
| `maxYear` | `number` | `currentYear + 10` | Maximum selectable year |
|
|
273
|
+
| `weekStartsOn` | `0 \| 1` | `0` | Week start day (0 = Sunday, 1 = Monday) |
|
|
274
|
+
| `onDateSelect` | `(date: Date) => void` | - | Callback when date is selected |
|
|
275
|
+
| `onEventClick` | `(event: CalendarEvent) => void` | - | Callback when event is clicked |
|
|
276
|
+
| `onMonthChange` | `(year: number, month: number) => void` | - | Callback when month changes |
|
|
277
|
+
|
|
278
|
+
### CalendarEvent Interface
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
interface CalendarEvent {
|
|
282
|
+
id: string | number;
|
|
283
|
+
name: string;
|
|
284
|
+
date: string | Date;
|
|
285
|
+
description?: string;
|
|
286
|
+
color?: string;
|
|
287
|
+
[key: string]: any;
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Framework-Specific Features
|
|
292
|
+
|
|
293
|
+
### React Props
|
|
294
|
+
|
|
295
|
+
| Prop | Type | Description |
|
|
296
|
+
| ---------------- | ------------------------------------- | ------------------------ |
|
|
297
|
+
| `className` | `string` | CSS class name |
|
|
298
|
+
| `style` | `React.CSSProperties` | Inline styles |
|
|
299
|
+
| `renderEvent` | `(event: CalendarEvent) => ReactNode` | Custom event renderer |
|
|
300
|
+
| `renderNoEvents` | `() => ReactNode` | Custom no events message |
|
|
301
|
+
|
|
302
|
+
### Vue Props & Slots
|
|
303
|
+
|
|
304
|
+
| Slot | Props | Description |
|
|
305
|
+
| ----------- | -------------------------- | ------------------------ |
|
|
306
|
+
| `title` | - | Custom title content |
|
|
307
|
+
| `event` | `{ event: CalendarEvent }` | Custom event display |
|
|
308
|
+
| `no-events` | - | Custom no events message |
|
|
309
|
+
|
|
310
|
+
### React Native Props
|
|
311
|
+
|
|
312
|
+
| Prop | Type | Description |
|
|
313
|
+
| ----------------- | ----------- | -------------------------- |
|
|
314
|
+
| `style` | `ViewStyle` | Container style |
|
|
315
|
+
| `headerStyle` | `ViewStyle` | Header style |
|
|
316
|
+
| `cellStyle` | `ViewStyle` | Calendar cell style |
|
|
317
|
+
| `showCloseButton` | `boolean` | Show close button in popup |
|
|
318
|
+
|
|
319
|
+
### Vanilla JavaScript Options
|
|
320
|
+
|
|
321
|
+
| Option | Type | Description |
|
|
322
|
+
| ---------------- | ---------------------------------- | ----------------------------- |
|
|
323
|
+
| `container` | `HTMLElement \| string` | Container element or selector |
|
|
324
|
+
| `className` | `string` | Additional CSS class |
|
|
325
|
+
| `renderEvent` | `(event: CalendarEvent) => string` | Custom event HTML renderer |
|
|
326
|
+
| `renderNoEvents` | `() => string` | Custom no events HTML |
|
|
327
|
+
|
|
328
|
+
### Vanilla JavaScript Events
|
|
329
|
+
|
|
330
|
+
```javascript
|
|
331
|
+
// Listen to calendar events
|
|
332
|
+
calendar.container.addEventListener('dateSelect', e => {
|
|
333
|
+
console.log('Date selected:', e.detail.date);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
calendar.container.addEventListener('monthChange', e => {
|
|
337
|
+
console.log('Month changed:', e.detail.year, e.detail.month);
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Vanilla JavaScript API
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
const calendar = createCalendar(options);
|
|
345
|
+
|
|
346
|
+
// Methods
|
|
347
|
+
calendar.updateEvents(newEvents); // Update events
|
|
348
|
+
calendar.getCurrentDate(); // Get selected date
|
|
349
|
+
calendar.goToDate(new Date()); // Navigate to date
|
|
350
|
+
calendar.getEngine(); // Access core engine
|
|
351
|
+
calendar.destroy(); // Cleanup
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Common Issues & Solutions
|
|
355
|
+
|
|
356
|
+
### Vanilla JavaScript
|
|
357
|
+
|
|
358
|
+
**Issue: "Function is not defined" errors with onclick handlers**
|
|
359
|
+
|
|
360
|
+
❌ **Wrong:**
|
|
361
|
+
|
|
362
|
+
```html
|
|
363
|
+
<button onclick="myFunction()">Click me</button>
|
|
364
|
+
<script type="module">
|
|
365
|
+
function myFunction() {} // Not accessible globally in modules
|
|
366
|
+
</script>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
✅ **Correct:**
|
|
370
|
+
|
|
371
|
+
```html
|
|
372
|
+
<button id="myButton">Click me</button>
|
|
373
|
+
<script type="module">
|
|
374
|
+
function myFunction() {}
|
|
375
|
+
document.getElementById('myButton').addEventListener('click', myFunction);
|
|
376
|
+
</script>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Issue: Module imports not working**
|
|
380
|
+
|
|
381
|
+
Use the correct import paths:
|
|
382
|
+
|
|
383
|
+
- Local: `'./dist/vanilla/index.mjs'`
|
|
384
|
+
- NPM: `'kalendly/vanilla'`
|
|
385
|
+
- CDN: `'https://unpkg.com/kalendly/dist/vanilla/index.mjs'`
|
|
386
|
+
|
|
387
|
+
**Issue: Styles not loading**
|
|
388
|
+
|
|
389
|
+
Always include the CSS file:
|
|
390
|
+
|
|
391
|
+
```html
|
|
392
|
+
<link rel="stylesheet" href="path/to/kalendly/dist/styles/calendar.css" />
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Customization
|
|
396
|
+
|
|
397
|
+
### CSS Variables (React/Vue)
|
|
398
|
+
|
|
399
|
+
```css
|
|
400
|
+
:root {
|
|
401
|
+
--calendar-primary-color: #fc8917;
|
|
402
|
+
--calendar-secondary-color: #fca045;
|
|
403
|
+
--calendar-tertiary-color: #fdb873;
|
|
404
|
+
--calendar-text-color: #2c3e50;
|
|
405
|
+
--calendar-border-color: #dee2e6;
|
|
406
|
+
--calendar-today-outline: #f7db04;
|
|
407
|
+
--calendar-event-indicator: #1890ff;
|
|
408
|
+
--calendar-background: #fff;
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### React Native Theming
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
import { calendarStyles } from 'kalendly/react-native';
|
|
416
|
+
|
|
417
|
+
// Customize styles
|
|
418
|
+
const customStyles = {
|
|
419
|
+
...calendarStyles,
|
|
420
|
+
container: {
|
|
421
|
+
...calendarStyles.container,
|
|
422
|
+
backgroundColor: '#f5f5f5',
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Core API
|
|
428
|
+
|
|
429
|
+
You can also use the core calendar engine directly:
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { CalendarEngine } from 'kalendly/core';
|
|
433
|
+
|
|
434
|
+
const engine = new CalendarEngine({
|
|
435
|
+
events: myEvents,
|
|
436
|
+
initialDate: new Date(),
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// Subscribe to changes
|
|
440
|
+
const unsubscribe = engine.subscribe(() => {
|
|
441
|
+
console.log('Calendar state changed');
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
// Get current state
|
|
445
|
+
const viewModel = engine.getViewModel();
|
|
446
|
+
const actions = engine.getActions();
|
|
447
|
+
|
|
448
|
+
// Navigate months
|
|
449
|
+
actions.next();
|
|
450
|
+
actions.previous();
|
|
451
|
+
actions.jump(2025, 5); // June 2025
|
|
452
|
+
|
|
453
|
+
// Clean up
|
|
454
|
+
unsubscribe();
|
|
455
|
+
engine.destroy();
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## TypeScript Support
|
|
459
|
+
|
|
460
|
+
The package is written in TypeScript and provides full type definitions:
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
import type { CalendarEvent, CalendarProps, CalendarState } from 'kalendly';
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Browser Support
|
|
467
|
+
|
|
468
|
+
- **React/Vue**: Modern browsers (Chrome 90+, Firefox 88+, Safari 14+)
|
|
469
|
+
- **React Native**: iOS 12+, Android API 21+
|
|
470
|
+
|
|
471
|
+
## Contributing
|
|
472
|
+
|
|
473
|
+
1. Fork the repository
|
|
474
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
475
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
476
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
477
|
+
5. Open a Pull Request
|
|
478
|
+
|
|
479
|
+
## License
|
|
480
|
+
|
|
481
|
+
MIT © Callis Ezenwaka
|
|
482
|
+
|
|
483
|
+
## Changelog
|
|
484
|
+
|
|
485
|
+
### 1.0.0
|
|
486
|
+
|
|
487
|
+
- Initial release
|
|
488
|
+
- React, Vue, and React Native support
|
|
489
|
+
- TypeScript definitions
|
|
490
|
+
- Core calendar engine
|
|
491
|
+
- Event management
|
|
492
|
+
- Responsive design
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
interface CalendarEvent {
|
|
2
|
+
id: string | number;
|
|
3
|
+
name: string;
|
|
4
|
+
date: string | Date;
|
|
5
|
+
description?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
interface CalendarDate {
|
|
10
|
+
date: Date;
|
|
11
|
+
isCurrentMonth: boolean;
|
|
12
|
+
isToday: boolean;
|
|
13
|
+
hasEvents: boolean;
|
|
14
|
+
events: CalendarEvent[];
|
|
15
|
+
}
|
|
16
|
+
interface CalendarState {
|
|
17
|
+
currentYear: number;
|
|
18
|
+
currentMonth: number;
|
|
19
|
+
currentDate: number;
|
|
20
|
+
selectedDate: Date | null;
|
|
21
|
+
selectedDayIndex: number | null;
|
|
22
|
+
tasks: CalendarEvent[];
|
|
23
|
+
}
|
|
24
|
+
interface CalendarConfig {
|
|
25
|
+
events: CalendarEvent[];
|
|
26
|
+
initialDate?: Date;
|
|
27
|
+
minYear?: number;
|
|
28
|
+
maxYear?: number;
|
|
29
|
+
weekStartsOn?: 0 | 1;
|
|
30
|
+
}
|
|
31
|
+
interface CalendarActions {
|
|
32
|
+
next: () => void;
|
|
33
|
+
previous: () => void;
|
|
34
|
+
jump: (year: number, month: number) => void;
|
|
35
|
+
selectDate: (date: Date) => void;
|
|
36
|
+
updateTasks: () => void;
|
|
37
|
+
}
|
|
38
|
+
interface PopupPosition {
|
|
39
|
+
class: 'popup-left' | 'popup-right' | 'popup-center-top' | 'popup-center-bottom';
|
|
40
|
+
style?: Record<string, string | number>;
|
|
41
|
+
}
|
|
42
|
+
interface CalendarViewModel extends CalendarState {
|
|
43
|
+
months: string[];
|
|
44
|
+
days: string[];
|
|
45
|
+
years: number[];
|
|
46
|
+
monthAndYearText: string;
|
|
47
|
+
scheduleDay: string;
|
|
48
|
+
calendarDates: (CalendarDate | null)[][];
|
|
49
|
+
popupPositionClass: string;
|
|
50
|
+
}
|
|
51
|
+
type CalendarEventHandler = (event: CalendarEvent) => void;
|
|
52
|
+
interface CalendarProps {
|
|
53
|
+
events: CalendarEvent[];
|
|
54
|
+
initialDate?: Date;
|
|
55
|
+
minYear?: number;
|
|
56
|
+
maxYear?: number;
|
|
57
|
+
weekStartsOn?: 0 | 1;
|
|
58
|
+
onDateSelect?: (date: Date) => void;
|
|
59
|
+
onEventClick?: CalendarEventHandler;
|
|
60
|
+
onMonthChange?: (year: number, month: number) => void;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
declare const MONTHS: string[];
|
|
64
|
+
declare const DAYS: string[];
|
|
65
|
+
/**
|
|
66
|
+
* Normalizes a date to midnight (00:00:00) for comparison purposes
|
|
67
|
+
*/
|
|
68
|
+
declare function normalizeDate(date: Date): Date;
|
|
69
|
+
/**
|
|
70
|
+
* Checks if two dates are the same day
|
|
71
|
+
*/
|
|
72
|
+
declare function isSameDay(date1: Date, date2: Date): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Checks if a date is today
|
|
75
|
+
*/
|
|
76
|
+
declare function isToday(date: Date): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Generates an array of years for the year selector
|
|
79
|
+
*/
|
|
80
|
+
declare function generateYears(minYear?: number, maxYear?: number): number[];
|
|
81
|
+
/**
|
|
82
|
+
* Gets events for a specific date
|
|
83
|
+
*/
|
|
84
|
+
declare function getEventsForDate(events: CalendarEvent[], date: Date): CalendarEvent[];
|
|
85
|
+
/**
|
|
86
|
+
* Checks if a date has any events
|
|
87
|
+
*/
|
|
88
|
+
declare function hasEvents(events: CalendarEvent[], date: Date): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Generates calendar dates for a given month and year
|
|
91
|
+
*/
|
|
92
|
+
declare function generateCalendarDates(year: number, month: number, events?: CalendarEvent[], weekStartsOn?: 0 | 1): (CalendarDate | null)[][];
|
|
93
|
+
/**
|
|
94
|
+
* Gets the popup position class based on the selected day index
|
|
95
|
+
*/
|
|
96
|
+
declare function getPopupPositionClass(selectedDayIndex: number | null): string;
|
|
97
|
+
/**
|
|
98
|
+
* Gets CSS classes for a calendar cell
|
|
99
|
+
*/
|
|
100
|
+
declare function getCellClasses(calendarDate: CalendarDate | null): string[];
|
|
101
|
+
/**
|
|
102
|
+
* Formats a date for display
|
|
103
|
+
*/
|
|
104
|
+
declare function formatDateForDisplay(date: Date): string;
|
|
105
|
+
/**
|
|
106
|
+
* Gets month and year text for display
|
|
107
|
+
*/
|
|
108
|
+
declare function getMonthYearText(year: number, month: number): string;
|
|
109
|
+
|
|
110
|
+
declare class CalendarEngine {
|
|
111
|
+
private state;
|
|
112
|
+
private config;
|
|
113
|
+
private listeners;
|
|
114
|
+
constructor(config: CalendarConfig);
|
|
115
|
+
/**
|
|
116
|
+
* Subscribe to state changes
|
|
117
|
+
*/
|
|
118
|
+
subscribe(listener: () => void): () => void;
|
|
119
|
+
/**
|
|
120
|
+
* Notify all listeners of state changes
|
|
121
|
+
*/
|
|
122
|
+
private notify;
|
|
123
|
+
/**
|
|
124
|
+
* Get current state
|
|
125
|
+
*/
|
|
126
|
+
getState(): CalendarState;
|
|
127
|
+
/**
|
|
128
|
+
* Get view model with computed properties
|
|
129
|
+
*/
|
|
130
|
+
getViewModel(): CalendarViewModel;
|
|
131
|
+
/**
|
|
132
|
+
* Get actions object
|
|
133
|
+
*/
|
|
134
|
+
getActions(): CalendarActions;
|
|
135
|
+
/**
|
|
136
|
+
* Navigate to next month
|
|
137
|
+
*/
|
|
138
|
+
private next;
|
|
139
|
+
/**
|
|
140
|
+
* Navigate to previous month
|
|
141
|
+
*/
|
|
142
|
+
private previous;
|
|
143
|
+
/**
|
|
144
|
+
* Jump to specific month and year
|
|
145
|
+
*/
|
|
146
|
+
private jump;
|
|
147
|
+
/**
|
|
148
|
+
* Select a specific date
|
|
149
|
+
*/
|
|
150
|
+
private selectDate;
|
|
151
|
+
/**
|
|
152
|
+
* Update tasks for the currently selected date
|
|
153
|
+
*/
|
|
154
|
+
private updateTasks;
|
|
155
|
+
/**
|
|
156
|
+
* Update events configuration
|
|
157
|
+
*/
|
|
158
|
+
updateEvents(events: CalendarEvent[]): void;
|
|
159
|
+
/**
|
|
160
|
+
* Handle date cell click
|
|
161
|
+
*/
|
|
162
|
+
handleDateClick(date: Date, dayIndex?: number): void;
|
|
163
|
+
/**
|
|
164
|
+
* Check if date has events
|
|
165
|
+
*/
|
|
166
|
+
hasEventsForDate(date: Date): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Get events for a specific date
|
|
169
|
+
*/
|
|
170
|
+
getEventsForDate(date: Date): CalendarEvent[];
|
|
171
|
+
/**
|
|
172
|
+
* Clear selected date
|
|
173
|
+
*/
|
|
174
|
+
clearSelection(): void;
|
|
175
|
+
/**
|
|
176
|
+
* Destroy the engine and cleanup listeners
|
|
177
|
+
*/
|
|
178
|
+
destroy(): void;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarProps, type CalendarState, type CalendarViewModel, DAYS, MONTHS, type PopupPosition, formatDateForDisplay, generateCalendarDates, generateYears, getCellClasses, getEventsForDate, getMonthYearText, getPopupPositionClass, hasEvents, isSameDay, isToday, normalizeDate };
|