simple-calendar-js 2.0.2 → 3.0.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 +1 -1
- package/README.md +364 -612
- 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 +8 -4
- package/dist/SimpleCalendarJs.min.css +0 -10
- package/dist/SimpleCalendarJs.min.js +0 -10
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SimpleCalendarJs v3.0.0 — Vue 3 Wrapper
|
|
3
|
+
* A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
|
|
4
|
+
*
|
|
5
|
+
* @author Pedro Lopes <simplecalendarjs@gmail.com>
|
|
6
|
+
* @homepage https://www.simplecalendarjs.com
|
|
7
|
+
* @license SEE LICENSE IN LICENSE
|
|
8
|
+
* @repository https://github.com/pclslopes/SimpleCalendarJs
|
|
9
|
+
*
|
|
10
|
+
* Exposed methods (via ref):
|
|
11
|
+
* const calRef = ref();
|
|
12
|
+
* calRef.value.setView('week');
|
|
13
|
+
* calRef.value.navigate(1);
|
|
14
|
+
* calRef.value.goToDate(new Date());
|
|
15
|
+
* calRef.value.goToToday();
|
|
16
|
+
* calRef.value.getInstance(); // Get raw instance
|
|
17
|
+
*
|
|
18
|
+
* Example with theme switching:
|
|
19
|
+
* <script setup>
|
|
20
|
+
* import { ref } from 'vue';
|
|
21
|
+
* import SimpleCalendarJsVue from './simple-calendar-js-vue.js';
|
|
22
|
+
*
|
|
23
|
+
* const isDark = ref(false);
|
|
24
|
+
* const view = ref('month');
|
|
25
|
+
*
|
|
26
|
+
* const fetchEvents = async (start, end) => {
|
|
27
|
+
* // Fetch events...
|
|
28
|
+
* return events;
|
|
29
|
+
* };
|
|
30
|
+
* </script>
|
|
31
|
+
*
|
|
32
|
+
* <template>
|
|
33
|
+
* <button @click="isDark = !isDark">Toggle Theme</button>
|
|
34
|
+
* <SimpleCalendarJsVue
|
|
35
|
+
* :defaultView="view"
|
|
36
|
+
* :darkMode="isDark"
|
|
37
|
+
* :fetchEvents="fetchEvents"
|
|
38
|
+
* />
|
|
39
|
+
* </template>
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
import { ref, onMounted, onUnmounted, watch, defineComponent, h } from 'vue';
|
|
43
|
+
|
|
44
|
+
// Props that require re-mounting when changed
|
|
45
|
+
const INIT_PROPS = [
|
|
46
|
+
'defaultView',
|
|
47
|
+
'defaultDate',
|
|
48
|
+
'weekStartsOn',
|
|
49
|
+
'locale',
|
|
50
|
+
'use24Hour',
|
|
51
|
+
'showTimeInItems',
|
|
52
|
+
'showGridLines',
|
|
53
|
+
'showToolbar',
|
|
54
|
+
'showTodayButton',
|
|
55
|
+
'showNavigation',
|
|
56
|
+
'showTitle',
|
|
57
|
+
'showYearPicker',
|
|
58
|
+
'showViewSwitcher',
|
|
59
|
+
'enabledViews',
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
// Callback props that map to Vue events
|
|
63
|
+
const CALLBACK_PROPS = ['fetchEvents', 'onEventClick', 'onSlotClick', 'onViewChange', 'onNavigate'];
|
|
64
|
+
|
|
65
|
+
export default defineComponent({
|
|
66
|
+
name: 'SimpleCalendarJs',
|
|
67
|
+
|
|
68
|
+
props: {
|
|
69
|
+
// Init-only props
|
|
70
|
+
defaultView: { type: String, default: 'month' },
|
|
71
|
+
defaultDate: { type: Date, default: null },
|
|
72
|
+
weekStartsOn: { type: Number, default: 0 },
|
|
73
|
+
locale: { type: String, default: 'default' },
|
|
74
|
+
use24Hour: { type: Boolean, default: false },
|
|
75
|
+
showTimeInItems: { type: Boolean, default: true },
|
|
76
|
+
showGridLines: { type: Boolean, default: true },
|
|
77
|
+
showToolbar: { type: Boolean, default: true },
|
|
78
|
+
showTodayButton: { type: Boolean, default: true },
|
|
79
|
+
showNavigation: { type: Boolean, default: true },
|
|
80
|
+
showTitle: { type: Boolean, default: true },
|
|
81
|
+
showYearPicker: { type: Boolean, default: true },
|
|
82
|
+
showViewSwitcher: { type: Boolean, default: true },
|
|
83
|
+
enabledViews: { type: Array, default: () => ['month', 'week', 'day'] },
|
|
84
|
+
|
|
85
|
+
// Callback props
|
|
86
|
+
fetchEvents: { type: Function, default: null },
|
|
87
|
+
|
|
88
|
+
// Theme prop
|
|
89
|
+
darkMode: { type: Boolean, default: false },
|
|
90
|
+
|
|
91
|
+
// Custom class
|
|
92
|
+
customClass: { type: String, default: '' },
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
emits: ['eventClick', 'slotClick', 'viewChange', 'navigate'],
|
|
96
|
+
|
|
97
|
+
setup(props, { emit, expose }) {
|
|
98
|
+
const containerRef = ref(null);
|
|
99
|
+
const instanceRef = ref(null);
|
|
100
|
+
|
|
101
|
+
// Helper to resolve SimpleCalendarJs class
|
|
102
|
+
const resolveClass = () => {
|
|
103
|
+
if (typeof SimpleCalendarJs !== 'undefined') return SimpleCalendarJs;
|
|
104
|
+
if (typeof window !== 'undefined' && window.SimpleCalendarJs) return window.SimpleCalendarJs;
|
|
105
|
+
return null;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Create calendar instance
|
|
109
|
+
const createCalendar = () => {
|
|
110
|
+
const Cal = resolveClass();
|
|
111
|
+
if (!Cal) {
|
|
112
|
+
console.error(
|
|
113
|
+
'SimpleCalendarJsVue: SimpleCalendarJs class not found. ' +
|
|
114
|
+
'Make sure simple-calendar-js.js is imported or loaded as a script.'
|
|
115
|
+
);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Destroy previous instance
|
|
120
|
+
if (instanceRef.value) {
|
|
121
|
+
instanceRef.value.destroy();
|
|
122
|
+
instanceRef.value = null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Build options
|
|
126
|
+
const options = {};
|
|
127
|
+
|
|
128
|
+
// Add init props
|
|
129
|
+
for (const key of INIT_PROPS) {
|
|
130
|
+
if (props[key] !== undefined) options[key] = props[key];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Add callback props with Vue event emitters
|
|
134
|
+
if (props.fetchEvents) {
|
|
135
|
+
options.fetchEvents = props.fetchEvents;
|
|
136
|
+
}
|
|
137
|
+
options.onEventClick = (event) => emit('eventClick', event);
|
|
138
|
+
options.onSlotClick = (date) => emit('slotClick', date);
|
|
139
|
+
options.onViewChange = (view) => emit('viewChange', view);
|
|
140
|
+
options.onNavigate = (start, end) => emit('navigate', start, end);
|
|
141
|
+
|
|
142
|
+
instanceRef.value = new Cal(containerRef.value, options);
|
|
143
|
+
|
|
144
|
+
// Apply dark mode if needed
|
|
145
|
+
if (props.darkMode) {
|
|
146
|
+
instanceRef.value._root.classList.add('uc-dark');
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Mount calendar
|
|
151
|
+
onMounted(() => {
|
|
152
|
+
createCalendar();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Cleanup
|
|
156
|
+
onUnmounted(() => {
|
|
157
|
+
instanceRef.value?.destroy();
|
|
158
|
+
instanceRef.value = null;
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Watch init props for changes (requires re-mount)
|
|
162
|
+
for (const key of INIT_PROPS) {
|
|
163
|
+
watch(
|
|
164
|
+
() => props[key],
|
|
165
|
+
() => {
|
|
166
|
+
createCalendar();
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Watch dark mode (no re-mount needed)
|
|
172
|
+
watch(
|
|
173
|
+
() => props.darkMode,
|
|
174
|
+
(isDark) => {
|
|
175
|
+
if (instanceRef.value) {
|
|
176
|
+
instanceRef.value._root.classList.toggle('uc-dark', isDark);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// Watch callback props (update without re-mount)
|
|
182
|
+
watch(
|
|
183
|
+
() => props.fetchEvents,
|
|
184
|
+
(newFn) => {
|
|
185
|
+
if (instanceRef.value && newFn) {
|
|
186
|
+
instanceRef.value._opts.fetchEvents = newFn;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Expose methods
|
|
192
|
+
expose({
|
|
193
|
+
setView: (view) => instanceRef.value?.setView(view),
|
|
194
|
+
navigate: (direction) => instanceRef.value?.navigate(direction),
|
|
195
|
+
goToDate: (date) => instanceRef.value?.goToDate(date),
|
|
196
|
+
goToToday: () => instanceRef.value?.goToToday(),
|
|
197
|
+
getInstance: () => instanceRef.value,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Render function
|
|
201
|
+
return () =>
|
|
202
|
+
h('div', {
|
|
203
|
+
ref: containerRef,
|
|
204
|
+
class: props.customClass,
|
|
205
|
+
style: { height: '100%', minHeight: '500px' },
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
});
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simple-calendar-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A clean, modern, and feature-rich JavaScript calendar component with zero dependencies. Responsive design and intuitive navigation.",
|
|
5
|
-
"main": "dist/
|
|
6
|
-
"style": "dist/
|
|
5
|
+
"main": "dist/simple-calendar-js.min.js",
|
|
6
|
+
"style": "dist/simple-calendar-js.min.css",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist/",
|
|
9
|
+
"frameworks/",
|
|
9
10
|
"LICENSE",
|
|
10
11
|
"README.md"
|
|
11
12
|
],
|
|
@@ -33,7 +34,10 @@
|
|
|
33
34
|
"day-view",
|
|
34
35
|
"dark-mode",
|
|
35
36
|
"ui-component",
|
|
36
|
-
"framework-agnostic"
|
|
37
|
+
"framework-agnostic",
|
|
38
|
+
"react",
|
|
39
|
+
"vue",
|
|
40
|
+
"angular"
|
|
37
41
|
],
|
|
38
42
|
"author": "Pedro Lopes <simplecalendarjs@gmail.com> (https://www.simplecalendarjs.com)",
|
|
39
43
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SimpleCalendarJs v2.0.2
|
|
3
|
-
* A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
|
|
4
|
-
*
|
|
5
|
-
* @author Pedro Lopes <simplecalendarjs@gmail.com>
|
|
6
|
-
* @homepage https://www.simplecalendarjs.com
|
|
7
|
-
* @license SEE LICENSE IN LICENSE
|
|
8
|
-
* @repository https://github.com/pclslopes/SimpleCalendarJs
|
|
9
|
-
*/
|
|
10
|
-
.sc-calendar{--sc-bg-primary:#ffffff;--sc-bg-secondary:#f8f9fa;--sc-bg-tertiary:#e9ecef;--sc-text-primary:#212529;--sc-text-secondary:#6c757d;--sc-text-muted:#adb5bd;--sc-border-color:#e9ecef;--sc-border-light:#dee2e6;--sc-accent-color:#4c6f94;--sc-accent-hover:#0056b3;--sc-today-bg:#e3f2fd;--sc-today-text:#dc3545;--sc-hover-bg:#f8f9fa;--sc-shadow:none;--sc-shadow-enabled:0 2px 10px rgba(0, 0, 0, 0.1);font-family:inherit;background:var(--sc-bg-primary);color:var(--sc-text-primary);box-shadow:var(--sc-shadow);overflow:hidden;width:100%;max-width:100%;display:flex;flex-direction:column}.sc-calendar.sc-shadow{--sc-shadow:var(--sc-shadow-enabled)}@media (prefers-color-scheme:dark){.sc-calendar{--sc-bg-primary:#1a1a1a;--sc-bg-secondary:#2d2d2d;--sc-bg-tertiary:#3a3a3a;--sc-text-primary:#ffffff;--sc-text-secondary:#b0b0b0;--sc-text-muted:#888888;--sc-border-color:#444444;--sc-border-light:#555555;--sc-accent-color:#4a90e2;--sc-accent-hover:#357abd;--sc-today-bg:#1a2f4a;--sc-today-text:#ff6b6b;--sc-hover-bg:#2d2d2d;--sc-shadow-enabled:0 2px 10px rgba(0, 0, 0, 0.5)}}[data-theme=dark] .sc-calendar{--sc-bg-primary:#1a1a1a;--sc-bg-secondary:#2d2d2d;--sc-bg-tertiary:#3a3a3a;--sc-text-primary:#ffffff;--sc-text-secondary:#b0b0b0;--sc-text-muted:#888888;--sc-border-color:#444444;--sc-border-light:#555555;--sc-accent-color:#4a90e2;--sc-accent-hover:#357abd;--sc-today-bg:#1a2f4a;--sc-today-text:#ff6b6b;--sc-hover-bg:#2d2d2d;--sc-shadow-enabled:0 2px 10px rgba(0, 0, 0, 0.5)}[data-theme=light] .sc-calendar{--sc-bg-primary:#ffffff;--sc-bg-secondary:#f8f9fa;--sc-bg-tertiary:#e9ecef;--sc-text-primary:#212529;--sc-text-secondary:#6c757d;--sc-text-muted:#adb5bd;--sc-border-color:#e9ecef;--sc-border-light:#dee2e6;--sc-accent-color:#4c6f94;--sc-accent-hover:#0056b3;--sc-today-bg:#e3f2fd;--sc-today-text:#dc3545;--sc-hover-bg:#f8f9fa;--sc-shadow-enabled:0 2px 10px rgba(0, 0, 0, 0.1)}.sc-calendar{background:var(--calendar-bg,var(--sc-bg-primary));color:var(--calendar-text,var(--sc-text-primary));height:100%}.sc-header{background:0 0;padding:16px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:12px}.sc-borders-both .sc-header,.sc-borders-horizontal .sc-header{border-bottom:1px solid var(--sc-border-color)}.sc-nav{display:flex;align-items:center;gap:8px;justify-self:start}.sc-title-container{position:relative;justify-self:center}.sc-title{margin:0;font-size:1.25rem;font-weight:600;color:var(--sc-text-primary);white-space:nowrap;text-align:center;user-select:none}.sc-title-month,.sc-title-year{cursor:pointer;padding:2px 4px;border-radius:3px;transition:background-color .2s ease}.sc-title-month:hover,.sc-title-year:hover{color:var(--sc-event-color,#4c6f94)}.sc-month-dropdown{position:absolute;top:100%;left:50%;transform:translateX(-50%);background:var(--sc-bg-primary);border:1px solid var(--sc-border-color);border-radius:4px;z-index:1000;min-width:120px;box-shadow:var(--sc-shadow-enabled);max-height:240px;overflow-y:auto}.sc-month-option{padding:4px 8px;font-size:.75rem;color:var(--sc-text-primary);cursor:pointer;transition:background-color .2s ease}.sc-month-option:hover{background:var(--sc-bg-tertiary)}.sc-month-option.sc-current{background:var(--sc-event-color,#4c6f94);color:#fff}.sc-month-option.sc-current:hover{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 85%,#000)}.sc-year-dropdown{position:absolute;top:100%;right:-20px;background:var(--sc-bg-primary);border:1px solid var(--sc-border-color);border-radius:4px;z-index:1000;min-width:100px;box-shadow:var(--sc-shadow-enabled);max-height:240px;overflow-y:auto}.sc-year-option{padding:4px 8px;font-size:.75rem;color:var(--sc-text-primary);cursor:pointer;transition:background-color .2s ease;text-align:center}.sc-year-option:hover{background:var(--sc-bg-tertiary)}.sc-year-option.sc-current{background:var(--sc-event-color,#4c6f94);color:#fff}.sc-year-option.sc-current:hover{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 85%,#000)}.sc-btn{background:0 0;border:1px solid var(--sc-border-light);border-radius:4px;padding:8px 12px;cursor:pointer;color:var(--sc-text-primary);font-size:.875rem;font-weight:500;transition:all .2s ease;min-width:36px;display:flex;align-items:center;justify-content:center}.sc-nav .sc-btn{background:0 0;border:none;font-size:1.2rem;padding:8px;min-width:32px;color:var(--sc-text-primary);font-weight:700}.sc-btn:hover{background:var(--sc-bg-tertiary);border-color:#adb5bd}.sc-nav .sc-btn:hover{background:var(--sc-bg-tertiary);color:var(--sc-text-primary)}.sc-btn:active{background:#dee2e6}.sc-nav .sc-btn:active{background:var(--sc-bg-tertiary)}.sc-view-switcher{display:flex;gap:4px;justify-self:end}.sc-view-btn.sc-active{background:var(--sc-event-color,#4c6f94);color:#fff;border-color:var(--sc-event-color,#4c6f94)}.sc-view-btn.sc-active:hover{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 85%,#000);border-color:color-mix(in srgb,var(--sc-event-color,#4c6f94) 85%,#000)}.sc-content{flex:1;height:100%;display:flex;flex-direction:column}.sc-view-container{flex:1;overflow:hidden;height:100%}.sc-month-view{height:100%;display:flex;flex-direction:column}.sc-weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:var(--sc-bg-secondary)}.sc-weekday{padding:12px 8px;text-align:center;font-weight:600;font-size:.875rem;color:var(--sc-text-secondary)}.sc-borders-both .sc-month-view .sc-weekdays,.sc-borders-vertical .sc-month-view .sc-weekdays{border-left:1px solid var(--sc-border-color);border-right:1px solid var(--sc-border-color)}.sc-borders-both .sc-month-view .sc-weekday,.sc-borders-vertical .sc-month-view .sc-weekday{border-right:1px solid var(--sc-border-color)}.sc-borders-both .sc-month-view .sc-weekday:nth-child(7n),.sc-borders-vertical .sc-month-view .sc-weekday:nth-child(7n){border-right:none}.sc-days-grid{display:grid;grid-template-columns:repeat(7,1fr);grid-template-rows:repeat(6,1fr);flex:1;overflow:visible}.sc-month-view.sc-fullday .sc-days-grid{grid-template-rows:repeat(6,auto);min-height:auto}.sc-month-view.sc-fullday .sc-day{display:flex;flex-direction:column;position:relative}.sc-day{display:flex;flex-direction:column;min-height:80px;cursor:pointer;transition:background-color .2s ease;overflow:visible}.sc-day:hover{background:var(--sc-hover-bg)}.sc-day-number{text-align:center;font-weight:500;margin-bottom:4px;font-size:.875rem;line-height:1.2}.sc-day.sc-other-month .sc-day-number{color:var(--sc-text-muted)}.sc-day.sc-today{background:var(--sc-today-bg)}.sc-day.sc-today .sc-day-number{color:var(--sc-today-text);font-weight:600}.sc-day-count-mode{display:flex;align-items:center;justify-content:center}.sc-day-content{text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center}.sc-day-count-mode .sc-day-number{font-size:1.125rem;font-weight:600;margin-bottom:4px}.sc-event-count{font-size:.7rem;font-weight:600;line-height:1.2;background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 15%,var(--sc-bg-tertiary));color:color-mix(in srgb,var(--sc-event-color,#4c6f94) 80%,#000);padding:2px 6px;border-radius:10px;display:inline-block;margin-top:2px;text-align:center;box-sizing:border-box}@media (prefers-color-scheme:light){.sc-event-count{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 15%,var(--sc-bg-tertiary));color:color-mix(in srgb,var(--sc-event-color,#4c6f94) 80%,#000)}}[data-theme=light] .sc-event-count{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 15%,var(--sc-bg-tertiary));color:color-mix(in srgb,var(--sc-event-color,#4c6f94) 80%,#000)}@media (prefers-color-scheme:dark){.sc-event-count{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 20%,var(--sc-bg-tertiary));color:color-mix(in srgb,var(--sc-event-color,#4c6f94) 30%,#fff)}}[data-theme=dark] .sc-event-count{background:color-mix(in srgb,var(--sc-event-color,#4c6f94) 20%,var(--sc-bg-tertiary));color:color-mix(in srgb,var(--sc-event-color,#4c6f94) 30%,#fff)}.sc-day-count-mode.sc-today .sc-event-count{background:var(--sc-event-color,#4c6f94);color:#fff}@media (prefers-color-scheme:light){.sc-day-count-mode.sc-today .sc-event-count{background:var(--sc-event-color,#4c6f94);color:#fff}}[data-theme=light] .sc-day-count-mode.sc-today .sc-event-count{background:var(--sc-event-color,#4c6f94);color:#fff}@media (prefers-color-scheme:dark){.sc-day-count-mode.sc-today .sc-event-count{background:var(--sc-event-color,#4c6f94);color:#fff}}[data-theme=dark] .sc-day-count-mode.sc-today .sc-event-count{background:var(--sc-event-color,#4c6f94);color:#fff}.sc-day-count-mode.sc-other-month .sc-event-count{background:var(--sc-bg-secondary);color:var(--sc-text-muted)}.sc-day-events{flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden;padding:4px}.sc-month-view.sc-fullday .sc-day-number{flex-shrink:0;margin-bottom:4px;padding:4px 6px 0 6px}.sc-event-day,.sc-event-month,.sc-event-time,.sc-event-week{background:var(--sc-event-color,#4c6f94);color:#fff;border-radius:3px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.sc-month-view .sc-event-month{padding:2px 6px;font-size:.75rem;height:18px;margin:1px 4px;min-width:0;display:block}.sc-month-view.sc-fullday .sc-event-month{position:relative;padding:2px 6px;border-radius:3px;min-height:18px;display:block;box-sizing:border-box;overflow:visible}.sc-month-view.sc-fullday .sc-event-text{font-size:.75rem;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:absolute;display:block;width:100%}.sc-month-view .sc-event-single{border-radius:3px}.sc-month-view .sc-event-start{border-radius:3px 0 0 3px}.sc-month-view .sc-event-middle{border-radius:0}.sc-month-view .sc-event-end{border-radius:0 3px 3px 0}.sc-month-view .sc-event-month.sc-event-start{border-radius:3px 0 0 3px}.sc-month-view .sc-event-month.sc-event-middle{border-radius:0}.sc-month-view .sc-event-month.sc-event-end{border-radius:0 3px 3px 0}.sc-month-view.sc-fullday .sc-event-month.sc-event-start{position:relative}.sc-month-view.sc-fullday .sc-event-month.sc-event-start::after{content:'';position:absolute;right:-2px;top:0;bottom:0;width:2px;background:inherit;z-index:10}.sc-month-view.sc-fullday .sc-event-month.sc-event-middle{position:relative}.sc-month-view.sc-fullday .sc-event-month.sc-event-middle::after,.sc-month-view.sc-fullday .sc-event-month.sc-event-middle::before{content:'';position:absolute;top:0;bottom:0;width:2px;background:inherit;z-index:10}.sc-month-view.sc-fullday .sc-event-month.sc-event-middle::before{left:-2px}.sc-month-view.sc-fullday .sc-event-month.sc-event-middle::after{right:-2px}.sc-month-view.sc-fullday .sc-event-month.sc-event-end{position:relative}.sc-month-view.sc-fullday .sc-event-month.sc-event-end::before{content:'';position:absolute;left:-2px;top:0;bottom:0;width:2px;background:inherit;z-index:10}.sc-month-view.sc-fullday .sc-event-month.sc-event-single{margin:1px 4px!important;border-radius:3px!important;z-index:1;position:relative}.sc-month-view.sc-fullday .sc-event-month.sc-event-start{margin:1px 0 1px 4px!important;border-radius:3px 0 0 3px!important;z-index:2;position:relative}.sc-month-view.sc-fullday .sc-event-month.sc-event-middle{margin:1px 0!important;border-radius:0!important;z-index:2;position:relative}.sc-month-view.sc-fullday .sc-event-month.sc-event-end{margin:1px 4px 1px 0!important;border-radius:0 3px 3px 0!important;z-index:2;position:relative}.sc-event-placeholder{opacity:0!important}.sc-month-view.sc-fullday .sc-event-placeholder{min-height:18px;padding:2px 6px;margin:1px 4px;display:block;box-sizing:border-box}.sc-week-view.sc-fullday .sc-event-placeholder{min-height:18px;padding:2px 6px;margin:1px 4px;display:block;box-sizing:border-box;line-height:.9em}.sc-week-view{height:100%;overflow-y:auto;overflow-x:hidden;display:grid;grid-template-columns:80px repeat(7,1fr);align-content:start}.sc-day-header,.sc-time-column-header{position:sticky;top:0;z-index:20;display:flex;flex-direction:column;justify-content:center;text-align:center;padding:12px 8px;background:var(--sc-bg-secondary);height:60px;box-sizing:border-box}.sc-week-view .sc-day-header.sc-today{background:var(--sc-today-bg)}.sc-day-name{font-size:.75rem;color:var(--sc-text-secondary);font-weight:500;margin-bottom:2px}.sc-day-header .sc-day-number{font-size:1.25rem;font-weight:600;color:var(--sc-text-primary)}.sc-week-view .sc-day-header.sc-today .sc-day-number{color:var(--sc-today-text);font-weight:600}.sc-day-column,.sc-time-slot{height:60px;position:relative;box-sizing:border-box}.sc-time-slot{background:var(--sc-bg-secondary);padding:4px 8px 8px 8px;font-size:.75rem;color:var(--sc-text-secondary);text-align:center;display:flex;align-items:flex-start;justify-content:center}.sc-time-slot:first-child,.sc-time-slot:last-child{background:var(--sc-bg-tertiary);color:#495057;font-weight:500;font-style:italic}.sc-day-column{cursor:pointer;background:var(--sc-bg-primary)}.sc-week-view .sc-day-column.sc-today{background:var(--sc-today-bg)}.sc-day-column:hover{background:var(--sc-hover-bg)}.sc-half-hour-line{position:absolute;top:50%;left:0;right:0;height:0;pointer-events:none;z-index:1}.sc-week-view .sc-event-time{position:absolute;top:4px;left:4px;right:4px;padding:2px 6px;font-size:.75rem;line-height:1.2;border-radius:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;z-index:5;min-height:18px;display:block;box-sizing:border-box;padding-top:3px;padding-bottom:1px}.sc-week-view .sc-event-single{border-radius:3px}.sc-week-view .sc-event-start{border-radius:3px 0 0 3px}.sc-week-view .sc-event-middle{border-radius:0}.sc-week-view .sc-event-end{border-radius:0 3px 3px 0}.sc-week-view.sc-fullday .sc-event{width:100%;margin:2px 4px;padding:2px 6px;font-size:.75rem;height:18px;min-width:0}.sc-week-view.sc-fullday .sc-event-start{margin-right:0}.sc-week-view.sc-fullday .sc-event-middle{margin-left:0;margin-right:0}.sc-week-view.sc-fullday .sc-event-end{margin-left:0}.sc-week-view.sc-fullday{height:auto;display:flex;flex-direction:column}.sc-week-view.sc-fullday .sc-weekdays{display:grid;grid-template-columns:repeat(7,1fr);background:var(--sc-bg-secondary)}.sc-week-view.sc-fullday .sc-weekday{padding:12px 8px;text-align:center;font-weight:600;font-size:.875rem;color:var(--sc-text-secondary)}.sc-borders-horizontal .sc-week-view.sc-fullday .sc-weekdays{border-bottom:1px solid var(--sc-border-color)}.sc-borders-both .sc-week-view.sc-fullday .sc-weekday,.sc-borders-vertical .sc-week-view.sc-fullday .sc-weekday{border-right:1px solid var(--sc-border-color)}.sc-borders-both .sc-week-view.sc-fullday .sc-weekday:nth-child(7n),.sc-borders-vertical .sc-week-view.sc-fullday .sc-weekday:nth-child(7n){border-right:1px solid var(--sc-border-color)}.sc-borders-both .sc-week-view.sc-fullday .sc-weekday:first-child,.sc-borders-vertical .sc-week-view.sc-fullday .sc-weekday:first-child{border-left:1px solid var(--sc-border-color)}.sc-week-view.sc-fullday .sc-days-grid{display:grid;grid-template-columns:repeat(7,1fr);grid-template-rows:1fr;flex:1;min-height:auto;overflow:visible}.sc-week-view.sc-fullday .sc-day{display:flex;flex-direction:column;min-height:80px;position:relative;cursor:pointer;transition:background-color .2s ease;overflow:visible}.sc-week-view.sc-fullday .sc-day:hover{background:var(--sc-hover-bg)}.sc-week-view.sc-fullday .sc-day-number{text-align:center;font-weight:500;margin-bottom:4px;font-size:.875rem;line-height:1.2;flex-shrink:0;padding:4px 6px 0 6px}.sc-week-view.sc-fullday .sc-day.sc-today{background:var(--sc-today-bg)}.sc-week-view.sc-fullday .sc-day.sc-today .sc-day-number{color:var(--sc-today-text);font-weight:600}.sc-week-view.sc-fullday .sc-event-week{position:relative;border-radius:3px;min-height:18px;padding:2px 6px;display:block;box-sizing:border-box;overflow:visible}.sc-week-view.sc-fullday .sc-event-text{font-size:.75rem;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:absolute;display:block;width:100%}.sc-week-view.sc-fullday .sc-event-week.sc-event-single{margin:1px 4px!important;border-radius:3px!important;z-index:1;position:relative}.sc-week-view.sc-fullday .sc-event-week.sc-event-start{margin:1px 0 1px 4px!important;border-radius:3px 0 0 3px!important;z-index:2;position:relative}.sc-week-view.sc-fullday .sc-event-week.sc-event-start::after{content:'';position:absolute;right:-2px;top:0;bottom:0;width:2px;background:inherit;z-index:10}.sc-week-view.sc-fullday .sc-event-week.sc-event-middle{margin:1px 0!important;border-radius:0!important;z-index:2;position:relative}.sc-week-view.sc-fullday .sc-event-week.sc-event-middle::after,.sc-week-view.sc-fullday .sc-event-week.sc-event-middle::before{content:'';position:absolute;top:0;bottom:0;width:2px;background:inherit;z-index:10}.sc-week-view.sc-fullday .sc-event-week.sc-event-middle::before{left:-2px}.sc-week-view.sc-fullday .sc-event-week.sc-event-middle::after{right:-2px}.sc-week-view.sc-fullday .sc-event-week.sc-event-end{margin:1px 4px 1px 0!important;border-radius:0 3px 3px 0!important;z-index:2;position:relative}.sc-week-view.sc-fullday .sc-event-week.sc-event-end::before{content:'';position:absolute;left:-2px;top:0;bottom:0;width:2px;background:inherit;z-index:10}.sc-day-view{height:100%;overflow-y:auto;overflow-x:hidden;max-height:calc(100vh - 200px);display:grid;grid-template-columns:80px 1fr;align-content:start}.sc-day-view.sc-fullday{display:flex;flex-direction:column;padding:0;grid-template-columns:none}.sc-day-view.sc-fullday .sc-day-header{position:sticky;top:0;z-index:10;background:var(--sc-bg-secondary);border-bottom:1px solid var(--sc-border-color);padding:16px;text-align:center;flex-shrink:0}.sc-day-view.sc-fullday .sc-day-name{font-size:.875rem;color:var(--sc-text-secondary);font-weight:500;margin-bottom:4px}.sc-day-view.sc-fullday .sc-day-number{font-size:1.5rem;font-weight:600;color:var(--sc-text-primary)}.sc-day-view.sc-fullday .sc-day-header.sc-today .sc-day-number{color:var(--sc-today-text)}.sc-day-view.sc-fullday .sc-day-events{flex:1;padding:16px;display:flex;flex-direction:column;gap:8px;overflow-y:auto;cursor:pointer}.sc-day-view .sc-event-time{position:absolute;top:4px;left:4px;right:4px;padding:2px 6px;font-size:.75rem;line-height:1.2;border-radius:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;z-index:5;min-height:18px;display:block;box-sizing:border-box;padding-top:3px;padding-bottom:1px}.sc-day-view .sc-event{width:100%;margin:2px 4px;padding:2px 6px;font-size:.75rem;height:18px;min-width:0}.sc-day-view .sc-event-single{border-radius:3px}.sc-day-view .sc-event-start{border-radius:3px 0 0 3px}.sc-day-view .sc-event-middle{border-radius:0}.sc-day-view .sc-event-end{border-radius:0 3px 3px 0}.sc-day-view.sc-fullday .sc-event-start{margin-right:0}.sc-day-view.sc-fullday .sc-event-middle{margin-left:0;margin-right:0}.sc-day-view.sc-fullday .sc-event-end{margin-left:0}.sc-day-view.sc-fullday .sc-event-day{position:relative;padding:2px 6px;border-radius:3px;margin:1px 4px;min-height:18px;box-sizing:border-box;display:block}.sc-day-view.sc-fullday .sc-event-text{font-size:.75rem;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:absolute;display:block;width:100%}@media (max-width:768px){.sc-header{grid-template-columns:1fr;grid-template-rows:auto auto auto;gap:8px;justify-items:center}.sc-view-switcher{grid-row:1;justify-self:center}.sc-title-container{grid-row:2;justify-self:center}.sc-title{font-size:1.125rem}.sc-nav{grid-row:3;justify-self:center}.sc-days-grid{min-height:360px;grid-template-rows:repeat(6,minmax(60px,1fr))}.sc-day-number{font-size:.75rem}.sc-day-count-mode .sc-day-number{font-size:1rem}.sc-event-count{font-size:.625rem;padding:1px 4px;min-width:14px}.sc-event-month{font-size:.6rem;padding:1px 3px;height:14px}.sc-day-view .sc-event-time,.sc-week-view .sc-event-time{top:3px;left:3px;right:3px;padding:1px 4px;padding-top:2px;padding-bottom:1px;font-size:.65rem;min-height:16px}.sc-weekday{padding:8px 4px;font-size:.75rem}.sc-week-header{min-height:50px}.sc-week-view{grid-template-columns:60px repeat(7,1fr)}.sc-week-view.sc-fullday{grid-template-columns:repeat(7,1fr)}.sc-day-header{padding:8px 4px}.sc-day-name{font-size:.625rem}.sc-day-header .sc-day-number{font-size:1rem}.sc-day-header.sc-today .sc-day-number{color:var(--sc-today-text);font-weight:600}.sc-time-slot{height:40px;padding:4px;font-size:.625rem}.sc-hour-slot{height:40px}.sc-day-view{grid-template-columns:60px 1fr;max-height:calc(100vh - 160px)}.sc-week-view{max-height:calc(100vh - 160px)}}@media (max-width:480px){.sc-calendar{border-radius:0;box-shadow:none;border:1px solid #e9ecef}.sc-header{padding:12px}.sc-btn{padding:6px 8px;font-size:.75rem;min-width:30px}.sc-title{font-size:1rem}.sc-day{min-height:50px;padding:2px}.sc-days-grid{min-height:300px;grid-template-rows:repeat(6,minmax(50px,1fr))}.sc-day-count-mode .sc-day-number{font-size:.875rem}.sc-event-count{font-size:.5rem;padding:1px 3px;min-width:12px}.sc-weekday{padding:6px 2px;font-size:.625rem}.sc-week-header{min-height:40px}.sc-week-view{grid-template-columns:50px repeat(7,1fr);max-height:calc(100vh - 140px)}.sc-week-view.sc-fullday{grid-template-columns:repeat(7,1fr)}.sc-time-slot{height:30px;padding:2px;font-size:.5rem}.sc-hour-slot{height:30px}.sc-day-view{grid-template-columns:50px 1fr;max-height:calc(100vh - 140px)}.sc-day-view .sc-event-time,.sc-week-view .sc-event-time{top:2px;left:2px;right:2px;padding:1px 3px;padding-top:2px;padding-bottom:0;font-size:.5rem;min-height:14px}}.sc-borders-both .sc-month-view .sc-days-grid{border-left:1px solid var(--sc-border-color);border-bottom:1px solid var(--sc-border-color)}.sc-borders-vertical .sc-month-view .sc-days-grid{border-left:1px solid var(--sc-border-color);border-bottom:none}.sc-borders-horizontal .sc-month-view .sc-days-grid{border-left:none;border-bottom:1px solid var(--sc-border-color)}.sc-borders-none .sc-month-view .sc-days-grid{border-left:none;border-bottom:none}.sc-borders-both .sc-day{border-right:1px solid var(--sc-border-color);border-top:1px solid var(--sc-border-color)}.sc-borders-vertical .sc-day{border-right:1px solid var(--sc-border-color);border-top:none}.sc-borders-horizontal .sc-day{border-right:none;border-top:1px solid var(--sc-border-color)}.sc-borders-none .sc-day{border-right:none;border-top:none}.sc-borders-both .sc-day-column,.sc-borders-both .sc-time-slot{border-right:1px solid var(--sc-border-color);border-bottom:1px solid var(--sc-border-color)}.sc-borders-vertical .sc-day-column,.sc-borders-vertical .sc-time-slot{border-right:1px solid var(--sc-border-color);border-bottom:none}.sc-borders-horizontal .sc-day-column,.sc-borders-horizontal .sc-time-slot{border-right:none;border-bottom:1px solid var(--sc-border-color)}.sc-borders-none .sc-day-column,.sc-borders-none .sc-time-slot{border-right:none;border-bottom:none}.sc-week-view:not(.sc-fullday) .sc-time-slot{border-bottom:1px solid var(--sc-border-color)!important}.sc-week-view:not(.sc-fullday) .sc-day-column{border-bottom:1px solid var(--sc-border-color)!important}.sc-borders-both .sc-week-view.sc-fullday .sc-day{border-right:1px solid var(--sc-border-color);border-bottom:1px solid var(--sc-border-color)}.sc-borders-both .sc-week-view.sc-fullday .sc-day:first-child{border-left:1px solid var(--sc-border-color)}.sc-borders-vertical .sc-week-view.sc-fullday .sc-day{border-right:1px solid var(--sc-border-color);border-bottom:none}.sc-borders-horizontal .sc-week-view.sc-fullday .sc-day{border-right:none;border-bottom:1px solid var(--sc-border-color)}.sc-borders-none .sc-week-view.sc-fullday .sc-day{border-right:none;border-bottom:none}.sc-borders-both .sc-day-header,.sc-borders-both .sc-time-column-header{border-right:1px solid var(--sc-border-color);border-bottom:1px solid var(--sc-border-color)}.sc-borders-both .sc-day-header:first-child,.sc-borders-both .sc-time-column-header:first-child,.sc-borders-vertical .sc-day-header:first-child,.sc-borders-vertical .sc-time-column-header:first-child{border-left:1px solid var(--sc-border-color)}.sc-borders-vertical .sc-day-header,.sc-borders-vertical .sc-time-column-header{border-right:1px solid var(--sc-border-color);border-bottom:none}.sc-borders-horizontal .sc-day-header,.sc-borders-horizontal .sc-time-column-header{border-right:none;border-bottom:1px solid var(--sc-border-color)}.sc-borders-none .sc-day-header,.sc-borders-none .sc-time-column-header{border-right:none;border-bottom:none}.sc-borders-both .sc-week-view:not(.sc-fullday){border-left:1px solid var(--sc-border-color);border-right:1px solid var(--sc-border-color)}.sc-borders-vertical .sc-week-view:not(.sc-fullday){border-left:1px solid var(--sc-border-color);border-right:1px solid var(--sc-border-color)}.sc-borders-both .sc-day-header:nth-child(8n),.sc-borders-vertical .sc-day-header:nth-child(8n){border-right:none}.sc-borders-both .sc-half-hour-line,.sc-borders-horizontal .sc-half-hour-line{border-top:1px dotted var(--sc-border-color)}.sc-borders-none .sc-half-hour-line,.sc-borders-vertical .sc-half-hour-line{border-top:none}.sc-week-view:not(.sc-fullday) .sc-half-hour-line{border-top:1px dotted var(--sc-border-color)!important}.sc-day-view:not(.sc-fullday) .sc-time-slot{border-bottom:1px solid var(--sc-border-color)!important}.sc-borders-both .sc-day-view:not(.sc-fullday) .sc-time-slot,.sc-borders-vertical .sc-day-view:not(.sc-fullday) .sc-time-slot{border-left:1px solid var(--sc-border-color)!important}.sc-day-view:not(.sc-fullday) .sc-day-column{border-bottom:1px solid var(--sc-border-color)!important}.sc-day-view:not(.sc-fullday) .sc-half-hour-line{border-top:1px dotted var(--sc-border-color)!important}.sc-borders-both .sc-month-view .sc-days-grid,.sc-borders-vertical .sc-month-view .sc-days-grid{border-right:1px solid var(--sc-border-color)}.sc-borders-both .sc-day:nth-child(7n),.sc-borders-vertical .sc-day:nth-child(7n){border-right:none}:root{--sc-event-border-color:#6c757d}.sc-event-borders .sc-event-day:not(.sc-event-placeholder),.sc-event-borders .sc-event-month:not(.sc-event-placeholder),.sc-event-borders .sc-event-time:not(.sc-event-placeholder),.sc-event-borders .sc-event-week:not(.sc-event-placeholder){border:1px solid var(--sc-event-border-color)}.sc-event-borders .sc-event-single:not(.sc-event-placeholder){border:1px solid var(--sc-event-border-color)}.sc-event-borders .sc-event-start:not(.sc-event-placeholder){border-left:1px solid var(--sc-event-border-color);border-top:1px solid var(--sc-event-border-color);border-bottom:1px solid var(--sc-event-border-color)}.sc-event-borders .sc-event-middle:not(.sc-event-placeholder){border-top:1px solid var(--sc-event-border-color);border-bottom:1px solid var(--sc-event-border-color)}.sc-event-borders .sc-event-end:not(.sc-event-placeholder){border-right:1px solid var(--sc-event-border-color);border-top:1px solid var(--sc-event-border-color);border-bottom:1px solid var(--sc-event-border-color)}.sc-week-view .sc-event-week{border-right:none}.sc-event-no-borders .sc-event-day,.sc-event-no-borders .sc-event-month,.sc-event-no-borders .sc-event-time,.sc-event-no-borders .sc-event-week{border:none!important}@media print{.sc-calendar{box-shadow:none;border:1px solid #000}.sc-header{background:#fff!important;-webkit-print-color-adjust:exact;print-color-adjust:exact}.sc-btn{display:none}.sc-view-switcher{display:none}}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SimpleCalendarJs v2.0.2
|
|
3
|
-
* A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
|
|
4
|
-
*
|
|
5
|
-
* @author Pedro Lopes <simplecalendarjs@gmail.com>
|
|
6
|
-
* @homepage https://www.simplecalendarjs.com
|
|
7
|
-
* @license SEE LICENSE IN LICENSE
|
|
8
|
-
* @repository https://github.com/pclslopes/SimpleCalendarJs
|
|
9
|
-
*/
|
|
10
|
-
class t{constructor(t,e={}){this.container="string"==typeof t?document.querySelector(t):t;const s=this.mergeColors({background:"#ffffff",backgroundSecondary:"#f8f9fa",backgroundTertiary:"#ecf0f1",text:"#212529",textSecondary:"#6c757d",textMuted:"#adb5bd",border:"#e9ecef",borderLight:"#dee2e6",accent:"#4c6f94",accentHover:"#0056b3",todayBg:"#e3f2fd",todayText:"#dc3545",hoverBg:"#f8f9fa",dark:{background:"#2d2d2d",backgroundSecondary:"#3a3a3a",backgroundTertiary:"#4a4a4a",text:"#ffffff",textSecondary:"#cccccc",textMuted:"#888888",border:"#444444",borderLight:"#555555",accent:"#4a90e2",accentHover:"#357abd",todayBg:"#1a2f4a",todayText:"#ff6b6b",hoverBg:"#2d2d2d"}},e.colors||{});this.options={view:"month",date:new Date,events:[],fulldayMode:!1,startHour:6,endHour:22,timeSlotMinutes:30,dayClick:null,eventClick:null,changeState:null,gridBorders:"both",eventBorders:!1,eventBorderColor:"#6c757d",defaultEventColor:"#4c6f94",showMonthButton:!0,showWeekButton:!0,showDayButton:!0,showNavigation:!0,weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],showWeekdayChars:null,labels:{month:"Month",week:"Week",day:"Day",events:"events",event:"event",before:"Before",after:"After"},colors:s,...e,colors:s},this.currentDate=new Date(this.options.date),this.view=this.options.view,this.events=this.options.events,this.eventsCallback="function"==typeof this.options.events?this.options.events:null,this.fulldayMode=this.options.fulldayMode,this.fetchedRanges=[],this.allCachedEvents=[],this.init()}mergeColors(t,e){const s={...t};return Object.keys(e).forEach(t=>{"dark"!==t&&void 0!==e[t]&&(s[t]=e[t])}),e.dark&&(s.dark={...t.dark},Object.keys(e.dark).forEach(t=>{void 0!==e.dark[t]&&(s.dark[t]=e.dark[t])})),s}init(){this.container.innerHTML=this.getCalendarTemplate(),this.applyGridBorders(),this.applyEventBorders(),this.applyEventColor(),this.applyViewButtonVisibility(),this.applyNavigationVisibility(),this.applyCustomColors(),this.bindEvents(),this.render()}getWeekdayDisplay(t){const e=this.options.weekdays[t];return null===this.options.showWeekdayChars?e:e.substring(0,this.options.showWeekdayChars)}triggerChangeState(){if(this.options.changeState){const t={view:this.view,date:new Date(this.currentDate),fulldayMode:this.fulldayMode,startHour:this.options.startHour,endHour:this.options.endHour,timeSlotMinutes:this.options.timeSlotMinutes};this.options.changeState(t)}}applyGridBorders(){const t=this.container.querySelector(".sc-calendar");t&&(t.classList.remove("sc-borders-both","sc-borders-vertical","sc-borders-horizontal","sc-borders-none"),t.classList.add(`sc-borders-${this.options.gridBorders}`))}applyEventBorders(){const t=this.container.querySelector(".sc-calendar");t&&(t.classList.remove("sc-event-borders","sc-event-no-borders"),this.options.eventBorders?(t.classList.add("sc-event-borders"),t.style.setProperty("--sc-event-border-color",this.options.eventBorderColor)):t.classList.add("sc-event-no-borders"))}applyEventColor(){const t=this.container.querySelector(".sc-calendar");t&&t.style.setProperty("--sc-event-color",this.options.defaultEventColor)}applyViewButtonVisibility(){const t=this.container.querySelector('[data-view="month"]'),e=this.container.querySelector('[data-view="week"]'),s=this.container.querySelector('[data-view="day"]');t&&(t.style.display=this.options.showMonthButton?"flex":"none"),e&&(e.style.display=this.options.showWeekButton?"flex":"none"),s&&(s.style.display=this.options.showDayButton?"flex":"none");const n=this.container.querySelector(".sc-view-switcher");if(n){const t=this.options.showMonthButton||this.options.showWeekButton||this.options.showDayButton;n.style.display=t?"flex":"none"}}applyNavigationVisibility(){const t=this.container.querySelector(".sc-nav");t&&(t.style.visibility=this.options.showNavigation?"visible":"hidden")}applyCustomColors(){if(!this.container.querySelector(".sc-calendar"))return;const t=this.options.colors,e=(t,e)=>void 0!==e?`--${t}: ${e} !important;`:"",s=`\n .sc-calendar {\n ${e("sc-bg-primary",t.background)}\n ${e("sc-bg-secondary",t.backgroundSecondary)}\n ${e("sc-bg-tertiary",t.backgroundTertiary)}\n ${e("sc-text-primary",t.text)}\n ${e("sc-text-secondary",t.textSecondary)}\n ${e("sc-text-muted",t.textMuted)}\n ${e("sc-border-color",t.border)}\n ${e("sc-border-light",t.borderLight)}\n ${e("sc-accent-color",t.accent)}\n ${e("sc-accent-hover",t.accentHover)}\n ${e("sc-today-bg",t.todayBg)}\n ${e("sc-today-text",t.todayText)}\n ${e("sc-hover-bg",t.hoverBg)}\n }\n\n ${t.dark?`\n [data-theme="dark"] .sc-calendar {\n ${e("sc-bg-primary",t.dark.background)}\n ${e("sc-bg-secondary",t.dark.backgroundSecondary)}\n ${e("sc-bg-tertiary",t.dark.backgroundTertiary)}\n ${e("sc-text-primary",t.dark.text)}\n ${e("sc-text-secondary",t.dark.textSecondary)}\n ${e("sc-text-muted",t.dark.textMuted)}\n ${e("sc-border-color",t.dark.border)}\n ${e("sc-border-light",t.dark.borderLight)}\n ${e("sc-accent-color",t.dark.accent)}\n ${e("sc-accent-hover",t.dark.accentHover)}\n ${e("sc-today-bg",t.dark.todayBg)}\n ${e("sc-today-text",t.dark.todayText)}\n ${e("sc-hover-bg",t.dark.hoverBg)}\n }\n `:""}\n `;let n=document.getElementById("sc-custom-colors");n||(n=document.createElement("style"),n.id="sc-custom-colors",document.head.appendChild(n)),n.textContent=s}getCalendarTemplate(){return`\n <div class="sc-calendar">\n <div class="sc-header">\n <div class="sc-nav">\n <button class="sc-btn sc-prev">←</button>\n <button class="sc-btn sc-next">→</button>\n </div>\n <div class="sc-title-container">\n <h2 class="sc-title">\n <span class="sc-title-month"></span>\n <span class="sc-title-year"></span>\n </h2>\n <div class="sc-month-dropdown" style="display: none;">\n ${this.options.months.map((t,e)=>`<div class="sc-month-option" data-month="${e}">${t}</div>`).join("")}\n </div>\n <div class="sc-year-dropdown" style="display: none;">\n </div>\n </div>\n <div class="sc-view-switcher">\n <button class="sc-btn sc-view-btn ${"month"===this.view?"sc-active":""}" data-view="month">${this.options.labels.month}</button>\n <button class="sc-btn sc-view-btn ${"week"===this.view?"sc-active":""}" data-view="week">${this.options.labels.week}</button>\n <button class="sc-btn sc-view-btn ${"day"===this.view?"sc-active":""}" data-view="day">${this.options.labels.day}</button>\n </div>\n </div>\n <div class="sc-content">\n <div class="sc-view-container"></div>\n </div>\n </div>\n `}bindEvents(){const t=this.container.querySelector(".sc-prev"),e=this.container.querySelector(".sc-next"),s=this.container.querySelectorAll(".sc-view-btn");t.addEventListener("click",()=>this.navigate("prev")),e.addEventListener("click",()=>this.navigate("next")),s.forEach(t=>{t.addEventListener("click",t=>{const e=t.target.dataset.view;this.setView(e)})}),this.container.addEventListener("click",t=>{this.handleCalendarClick(t)}),this.outsideClickBound||(document.addEventListener("click",t=>{t.target.closest(".sc-title-container")||(this.hideMonthDropdown(),this.hideYearDropdown())}),this.outsideClickBound=!0)}bindMonthViewDropdowns(){if("month"!==this.view)return;const t=this.container.querySelector(".sc-title-month"),e=this.container.querySelector(".sc-title-year");if(t){const e=t.cloneNode(!0);t.parentNode.replaceChild(e,t),e.addEventListener("click",t=>{t.stopPropagation(),this.hideYearDropdown(),this.toggleMonthDropdown()})}if(e){const t=e.cloneNode(!0);e.parentNode.replaceChild(t,e),t.addEventListener("click",t=>{t.stopPropagation(),this.hideMonthDropdown(),this.toggleYearDropdown()})}this.generateYearOptions(),this.dropdownOptionsHandler&&this.container.removeEventListener("click",this.dropdownOptionsHandler),this.dropdownOptionsHandler=t=>{if(t.target.classList.contains("sc-month-option")){const e=parseInt(t.target.getAttribute("data-month"));this.setMonth(e),this.hideMonthDropdown()}else if(t.target.classList.contains("sc-year-option")){const e=parseInt(t.target.getAttribute("data-year"));this.setYear(e),this.hideYearDropdown()}},this.container.addEventListener("click",this.dropdownOptionsHandler);this.container.querySelectorAll(".sc-month-option"),this.container.querySelectorAll(".sc-year-option")}calculatePreciseTime(t,e){const s=t.getAttribute("data-time");if(!s)return null;const n=t.getBoundingClientRect(),i=e.clientY-n.top>n.height/2,a=this.parseTimeString(s);return a?(i&&a.setMinutes(a.getMinutes()+30),this.formatTime(a)):s}handleCalendarClick(t){if(t.target.classList.contains("sc-title-month")||t.target.classList.contains("sc-title-year")||t.target.classList.contains("sc-month-option")||t.target.classList.contains("sc-year-option")||t.target.closest(".sc-month-dropdown")||t.target.closest(".sc-year-dropdown"))return;const e=t.target.closest("[data-event-id]");if(e)return t.stopPropagation(),void this.handleEventClick(e,t);const s=t.target.closest("[data-date]");s&&this.handleDayClick(s,t)}handleEventClick(t,e){if(!this.options.eventClick)return;const s=t.getAttribute("data-event-id"),n=t.closest("[data-date]"),i=n?n.getAttribute("data-date"):null;if(s&&i){const t=new Date(i),a=this.getAllEventsForRange().find(t=>t.id==s);if(a){const s={date:t,time:this.calculatePreciseTime(n,e)};this.options.eventClick(a,s,e)}}}handleDayClick(t,e){if(!this.options.dayClick)return;const s=t.getAttribute("data-date");if(s){const n={date:new Date(s),time:this.calculatePreciseTime(t,e)};this.options.dayClick(n,e)}}navigate(t){const e="next"===t?1:-1;switch(this.view){case"month":this.currentDate.setMonth(this.currentDate.getMonth()+e);break;case"week":this.currentDate.setDate(this.currentDate.getDate()+7*e);break;case"day":this.currentDate.setDate(this.currentDate.getDate()+e)}this.render(),this.triggerChangeState()}toggleMonthDropdown(){if("month"!==this.view)return;const t=this.container.querySelector(".sc-month-dropdown");if(t){"none"!==t.style.display?this.hideMonthDropdown():(this.updateMonthDropdownSelection(),t.style.display="block",this.scrollToActiveMonth())}}hideMonthDropdown(){const t=this.container.querySelector(".sc-month-dropdown");t&&(t.style.display="none")}updateMonthDropdownSelection(){const t=this.container.querySelectorAll(".sc-month-option"),e=this.currentDate.getMonth();t.forEach((t,s)=>{t.classList.remove("sc-current"),s===e&&t.classList.add("sc-current")})}toggleYearDropdown(){if("month"!==this.view)return;const t=this.container.querySelector(".sc-year-dropdown");if(t){"none"!==t.style.display?this.hideYearDropdown():(this.generateYearOptions(),this.updateYearDropdownSelection(),t.style.display="block",this.scrollToActiveYear())}}hideYearDropdown(){const t=this.container.querySelector(".sc-year-dropdown");t&&(t.style.display="none")}generateYearOptions(){const t=this.container.querySelector(".sc-year-dropdown"),e=this.currentDate.getFullYear(),s=e+10;if(t){let n="";for(let t=e-10;t<=s;t++)n+=`<div class="sc-year-option" data-year="${t}">${t}</div>`;t.innerHTML=n}}updateYearDropdownSelection(){const t=this.container.querySelectorAll(".sc-year-option"),e=this.currentDate.getFullYear();t.forEach(t=>{t.classList.remove("sc-current"),parseInt(t.getAttribute("data-year"))===e&&t.classList.add("sc-current")})}setYear(t){this.currentDate.setFullYear(t),this.render(),this.triggerChangeState()}scrollToActiveMonth(){const t=this.container.querySelector(".sc-month-dropdown"),e=t?.querySelector(".sc-month-option.sc-current");t&&e&&setTimeout(()=>{t.getBoundingClientRect(),e.getBoundingClientRect(),t.scrollTop;const s=e.offsetTop-t.clientHeight/2+e.offsetHeight/2;t.scrollTop=s},0)}scrollToActiveYear(){const t=this.container.querySelector(".sc-year-dropdown"),e=t?.querySelector(".sc-year-option.sc-current");t&&e&&setTimeout(()=>{t.getBoundingClientRect(),e.getBoundingClientRect(),t.scrollTop;const s=e.offsetTop-t.clientHeight/2+e.offsetHeight/2;t.scrollTop=s},0)}setMonth(t){this.currentDate.setMonth(t),this.render(),this.triggerChangeState()}setView(t){this.view=t,this.container.querySelectorAll(".sc-view-btn").forEach(t=>{t.classList.remove("sc-active")}),this.container.querySelector(`[data-view="${t}"]`).classList.add("sc-active"),this.hideMonthDropdown(),this.hideYearDropdown(),this.render(),this.triggerChangeState()}render(){this.updateTitle(),this.renderView(),"month"===this.view&&this.bindMonthViewDropdowns()}updateTitle(){const t=this.container.querySelector(".sc-title"),e=this.container.querySelector(".sc-title-month"),s=this.container.querySelector(".sc-title-year");switch(this.view){case"month":e&&s?(e.textContent=this.options.months[this.currentDate.getMonth()],s.textContent=this.currentDate.getFullYear()):t.innerHTML=`<span class="sc-title-month">${this.options.months[this.currentDate.getMonth()]}</span> <span class="sc-title-year">${this.currentDate.getFullYear()}</span>`;break;case"week":const n=this.getWeekStart(this.currentDate),i=new Date(n);i.setDate(i.getDate()+6),t.textContent=`${this.options.months[n.getMonth()]} ${n.getDate()} - ${this.options.months[i.getMonth()]} ${i.getDate()}, ${n.getFullYear()}`;break;case"day":t.textContent=`${this.options.weekdays[this.currentDate.getDay()]}, ${this.options.months[this.currentDate.getMonth()]} ${this.currentDate.getDate()}, ${this.currentDate.getFullYear()}`}}renderView(){const t=this.container.querySelector(".sc-view-container");switch(this.view){case"month":t.innerHTML=this.renderMonthView();break;case"week":t.innerHTML=this.renderWeekView();break;case"day":t.innerHTML=this.renderDayView()}}renderMonthView(){const t=this.currentDate.getFullYear(),e=this.currentDate.getMonth(),s=new Date(t,e,1),n=new Date(s);n.setDate(n.getDate()-s.getDay());let i=`\n <div class="sc-month-view ${this.fulldayMode?"sc-fullday":""}">\n <div class="sc-weekdays">\n ${this.options.weekdays.map((t,e)=>`<div class="sc-weekday">${this.getWeekdayDisplay(e)}</div>`).join("")}\n </div>\n <div class="sc-days-grid">\n `;for(let t=0;t<6;t++)for(let s=0;s<7;s++){const a=new Date(n);a.setDate(n.getDate()+7*t+s);const o=a.getMonth()===e,r=this.isToday(a),c=this.getEventsForDate(a);if(this.fulldayMode){const t=this.addEventPlaceholders(c,a);i+=`\n <div class="sc-day ${o?"sc-current-month":"sc-other-month"} ${r?"sc-today":""}" data-date="${a.toISOString()}">\n <div class="sc-day-number">${a.getDate()}</div>\n ${t.map(t=>{if(t.isPlaceholder)return'<div class="sc-event-month sc-event-single sc-event-placeholder"> </div>';const e=this.getEventPosition(t.event,a),s=e.isSingle?"sc-event-single":e.isStart?"sc-event-start":e.isEnd?"sc-event-end":"sc-event-middle",n=e.isSingle||e.isStart?t.event.title:"",i=this.applyEventStyles(t.event);return`<div class="sc-event-month ${s}" data-event-id="${t.event.id}" ${i}><span class="sc-event-text">${n}</span></div>`}).join("")}\n </div>\n `}else{const t=c.length,e=0===t?"":1===t?`1 ${this.options.labels.event}`:`${t} ${this.options.labels.events}`;i+=`\n <div class="sc-day sc-day-count-mode ${o?"sc-current-month":"sc-other-month"} ${r?"sc-today":""}" data-date="${a.toISOString()}">\n <div class="sc-day-content">\n <div class="sc-day-number">${a.getDate()}</div>\n ${e?`<div class="sc-event-count">${e}</div>`:""}\n </div>\n </div>\n `}}return i+="\n </div>\n </div>\n ",i}renderWeekView(){const t=this.getWeekStart(this.currentDate),e=[];for(let s=0;s<7;s++){const n=new Date(t);n.setDate(n.getDate()+s),e.push(n)}if(this.fulldayMode)return this.renderWeekFullday(e);const s=this.generateTimeSlots();return`\n <div class="sc-week-view">\n <div class="sc-time-column-header"></div>\n ${e.map(t=>`\n <div class="sc-day-header ${this.isToday(t)?"sc-today":""}">\n <div class="sc-day-name">${this.getWeekdayDisplay(t.getDay())}</div>\n <div class="sc-day-number">${t.getDate()}</div>\n </div>\n `).join("")}\n ${s.map(t=>`\n <div class="sc-time-slot">${t}</div>\n ${e.map(e=>{const s=this.getEventsForTimeSlot(e,t);return`\n <div class="sc-day-column ${this.isToday(e)?"sc-today":""}" data-date="${e.toISOString()}" data-time="${t}">\n <div class="sc-half-hour-line"></div>\n ${s.map(t=>{const e=this.applyEventStyles(t);return`<div class="sc-event-time" data-event-id="${t.id}" ${e}>${t.title}</div>`}).join("")}\n </div>\n `}).join("")}\n `).join("")}\n </div>\n `}renderWeekFullday(t){return`\n <div class="sc-week-view sc-fullday">\n <div class="sc-weekdays">\n ${t.map(t=>`<div class="sc-weekday">${this.getWeekdayDisplay(t.getDay())}</div>`).join("")}\n </div>\n <div class="sc-days-grid">\n ${t.map(t=>{const e=this.isToday(t),s=this.getEventsForDate(t),n=this.addEventPlaceholders(s,t);return`\n <div class="sc-day ${e?"sc-today":""}" data-date="${t.toISOString()}">\n <div class="sc-day-number">${t.getDate()}</div>\n ${n.map(e=>{if(e.isPlaceholder)return'<div class="sc-event-week sc-event-single sc-event-placeholder"> </div>';const s=this.getEventPosition(e.event,t),n=s.isSingle?"sc-event-single":s.isStart?"sc-event-start":s.isEnd?"sc-event-end":"sc-event-middle",i=s.isSingle||s.isStart?e.event.title:"",a=this.applyEventStyles(e.event);return`<div class="sc-event-week ${n}" data-event-id="${e.event.id}" ${a}><span class="sc-event-text">${i}</span></div>`}).join("")}\n </div>\n `}).join("")}\n </div>\n </div>\n `}renderDayView(){const t=new Date(this.currentDate);if(this.fulldayMode){const e=this.getEventsForDate(t);return`\n <div class="sc-day-view sc-fullday">\n <div class="sc-day-header ${this.isToday(t)?"sc-today":""}">\n <div class="sc-day-name">${this.options.weekdays[t.getDay()]}</div>\n <div class="sc-day-number">${t.getDate()}</div>\n </div>\n <div class="sc-day-events" data-date="${t.toISOString()}">\n ${e.map(e=>{const s=this.getEventPosition(e,t),n=s.isSingle?"sc-event-single":s.isStart?"sc-event-start":s.isEnd?"sc-event-end":"sc-event-middle",i=e.title,a=this.applyEventStyles(e);return`<div class="sc-event-day ${n}" data-event-id="${e.id}" ${a}><span class="sc-event-text">${i}</span></div>`}).join("")}\n </div>\n </div>\n `}const e=this.generateTimeSlots();return`\n <div class="sc-day-view">\n <div class="sc-time-column-header"></div>\n <div class="sc-day-header ${this.isToday(t)?"sc-today":""}">\n <div class="sc-day-name">${this.options.weekdays[t.getDay()]}</div>\n <div class="sc-day-number">${t.getDate()}</div>\n </div>\n ${e.map(e=>{const s=this.getEventsForTimeSlot(t,e);return`\n <div class="sc-time-slot">${e}</div>\n <div class="sc-day-column ${this.isToday(t)?"sc-today":""}" data-date="${t.toISOString()}" data-time="${e}">\n <div class="sc-half-hour-line"></div>\n ${s.map(t=>{const e=this.applyEventStyles(t);return`<div class="sc-event-time" data-event-id="${t.id}" ${e}>${t.title}</div>`}).join("")}\n </div>\n `}).join("")}\n </div>\n `}generateTimeSlots(){const t=[],e=this.options.startHour,s=this.options.endHour,n=new Date;n.setHours(e,0,0,0),t.push(`${this.options.labels.before} ${this.formatTime(n)}`);for(let n=e;n<=s;n++){const e=new Date;e.setHours(n,0,0,0),t.push(this.formatTime(e))}const i=new Date;return i.setHours(s,0,0,0),t.push(`${this.options.labels.after} ${this.formatTime(i)}`),t}formatTime(t){return t.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0})}getWeekStart(t){const e=new Date(t);return e.setDate(e.getDate()-e.getDay()),e}getVisibleDateRange(){const t=this.currentDate.getFullYear(),e=this.currentDate.getMonth();switch(this.view){case"month":const s=new Date(t,e,1),n=new Date(s);n.setDate(n.getDate()-s.getDay());const i=new Date(n);return i.setDate(i.getDate()+41),{startDate:n,endDate:i};case"week":const a=this.getWeekStart(this.currentDate),o=new Date(a);return o.setDate(o.getDate()+6),{startDate:a,endDate:o};case"day":const r=new Date(this.currentDate);r.setHours(0,0,0,0);const c=new Date(r);return c.setHours(23,59,59,999),{startDate:r,endDate:c}}}isToday(t){const e=new Date;return t.toDateString()===e.toDateString()}isRangeCovered(t,e){for(const s of this.fetchedRanges)if(s.startDate<=t&&s.endDate>=e)return!0;return!1}getMissingRanges(t,e){const s=[];let n=new Date(t);const i=[...this.fetchedRanges].sort((t,e)=>t.startDate-e.startDate);for(const t of i){if(n<t.startDate&&n<=e){const i=new Date(Math.min(t.startDate.getTime()-864e5,e.getTime()));i>=n&&s.push({startDate:new Date(n),endDate:i})}t.endDate>=n&&(n=new Date(t.endDate.getTime()+864e5))}return n<=e&&s.push({startDate:new Date(n),endDate:new Date(e)}),s}addFetchedRange(t,e,s){const n={startDate:new Date(t),endDate:new Date(e),events:s};this.allCachedEvents=this.allCachedEvents.concat(s),this.fetchedRanges.push(n),this.mergeOverlappingRanges()}mergeOverlappingRanges(){this.fetchedRanges.sort((t,e)=>t.startDate-e.startDate);const t=[];for(const e of this.fetchedRanges)if(0===t.length||t[t.length-1].endDate<e.startDate)t.push(e);else{const s=t[t.length-1];s.endDate=new Date(Math.max(s.endDate.getTime(),e.endDate.getTime())),s.events=s.events.concat(e.events)}this.fetchedRanges=t,this.allCachedEvents=[];for(const t of this.fetchedRanges)this.allCachedEvents=this.allCachedEvents.concat(t.events)}getAllEventsForRange(){if(this.eventsCallback){const t=this.getVisibleDateRange();if(this.isRangeCovered(t.startDate,t.endDate))return this.allCachedEvents;const e=this.getMissingRanges(t.startDate,t.endDate);for(const t of e){const e=this.eventsCallback(t);this.addFetchedRange(t.startDate,t.endDate,e)}return this.allCachedEvents}return this.events||[]}getEventsForDate(t){return this.getAllEventsForRange().filter(e=>{const s=new Date(e.startDate||e.date),n=new Date(e.endDate||e.date),i=new Date(t);return i.setHours(0,0,0,0),s.setHours(0,0,0,0),n.setHours(0,0,0,0),i>=s&&i<=n}).sort((t,e)=>{const s=this.isMultiDayEvent(t),n=this.isMultiDayEvent(e);return s&&!n?-1:!s&&n?1:0})}getEventsForTimeSlot(t,e){if(this.fulldayMode)return this.getEventsForDate(t);return this.getEventsForDate(t).filter(t=>{if(!t.time)return!1;const s=this.parseTimeString(t.time);if(!s)return!1;const n=s.getHours(),i=this.options.startHour,a=this.options.endHour;if(e.startsWith(this.options.labels.before))return n<i;if(e.startsWith(this.options.labels.after))return n>a;const o=this.parseTimeString(e);if(!o)return!1;return n===o.getHours()})}parseTimeString(t){try{const e=new Date,[s,n]=t.split(" "),[i,a]=s.split(":").map(Number);let o=i;return"PM"===n&&12!==i&&(o+=12),"AM"===n&&12===i&&(o=0),e.setHours(o,a||0,0,0),e}catch(t){return null}}isMultiDayEvent(t){const e=new Date(t.startDate||t.date),s=new Date(t.endDate||t.date);return e.setHours(0,0,0,0),s.setHours(0,0,0,0),e.getTime()!==s.getTime()}addEventPlaceholders(t,e){if(!this.fulldayMode)return t.map(t=>({event:t,isPlaceholder:!1}));const s=this.getWeekStart(e),n=[];for(let t=0;t<7;t++){const e=new Date(s);e.setDate(e.getDate()+t),n.push(e)}const i=new Map;n.forEach(t=>{this.getEventsForDate(t).filter(t=>this.isMultiDayEvent(t)).forEach(t=>{i.has(t.id)||i.set(t.id,t)})});const a=Array.from(i.values()).sort((t,e)=>new Date(t.startDate||t.date)-new Date(e.startDate||e.date)),o=[],r=t.filter(t=>this.isMultiDayEvent(t)),c=t.filter(t=>!this.isMultiDayEvent(t));return a.forEach(t=>{const n=r.find(e=>e.id===t.id);if(n)o.push({event:n,isPlaceholder:!1});else{const n=new Date(t.startDate||t.date),i=new Date(t.endDate||t.date);n.setHours(0,0,0,0),i.setHours(0,0,0,0);const a=new Date(e);a.setHours(0,0,0,0);const r=new Date(s);r.setHours(0,0,0,0);const c=new Date(s);c.setDate(c.getDate()+6),c.setHours(0,0,0,0);n<=c&&(i>=r&&i<=c)&&a>i&&o.push({isPlaceholder:!0,eventId:t.id})}}),c.forEach(t=>{o.push({event:t,isPlaceholder:!1})}),o}getEventPosition(t,e){const s=new Date(t.startDate||t.date),n=new Date(t.endDate||t.date),i=new Date(e);s.setHours(0,0,0,0),n.setHours(0,0,0,0),i.setHours(0,0,0,0);return{isStart:i.getTime()===s.getTime(),isEnd:i.getTime()===n.getTime(),isMiddle:i>s&&i<n,isSingle:s.getTime()===n.getTime()}}addEvent(t){this.eventsCallback||(this.events.push(t),this.render())}removeEvent(t){this.eventsCallback||(this.events=this.events.filter(e=>e.id!==t),this.render())}setEvents(t){"function"==typeof t?(this.eventsCallback=t,this.events=[]):(this.events=t||[],this.eventsCallback=null),this.fetchedRanges=[],this.allCachedEvents=[],this.render()}setFulldayMode(t){this.fulldayMode=t,this.render(),this.triggerChangeState()}goToDate(t){this.currentDate=new Date(t),this.render(),this.triggerChangeState()}goToToday(){this.currentDate=new Date,this.render(),this.triggerChangeState()}setGridBorders(t){this.options.gridBorders=t,this.applyGridBorders()}setEventBorders(t){this.options.eventBorders=t,this.applyEventBorders(),this.render()}setEventBorderColor(t){this.options.eventBorderColor=t,this.applyEventBorders(),this.render()}setShowMonthButton(t){this.options.showMonthButton=t,this.applyViewButtonVisibility()}setShowWeekButton(t){this.options.showWeekButton=t,this.applyViewButtonVisibility()}setShowDayButton(t){this.options.showDayButton=t,this.applyViewButtonVisibility()}setViewButtonsVisibility(t,e,s){this.options.showMonthButton=t,this.options.showWeekButton=e,this.options.showDayButton=s,this.applyViewButtonVisibility()}setShowNavigation(t){this.options.showNavigation=t,this.applyNavigationVisibility()}setDefaultEventColor(t){this.options.defaultEventColor=t,this.applyEventColor(),this.render()}getEventBaseCssStyle(t){const e=t.color,s=!0===t.colorIsGradient,n=e?t.color:this.options.defaultEventColor;if(!n)return{};const i=(" "+n).slice(1),a=this.hexToRgb(i);if(!a)return{};const o=this.getOptimalTextColor(a);if(s){const t={r:Math.min(255,a.r+40),g:Math.min(255,a.g+40),b:Math.min(255,a.b+40)};return{"background-image":`linear-gradient(to bottom, ${this.rgbToHex(t)} 0px, ${n} 100%)`,"background-repeat":"repeat-x",color:o,"background-color":n}}return{"background-color":n,color:o}}getOptimalTextColor(t){return this.getLuminance(t)>.5?"#000000":"#ffffff"}getLuminance(t){return.2126*this.getRelativeLuminanceComponent(t.r/255)+.7152*this.getRelativeLuminanceComponent(t.g/255)+.0722*this.getRelativeLuminanceComponent(t.b/255)}getRelativeLuminanceComponent(t){return t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)}getContrastRatio(t,e){const s=this.getLuminance(t),n=this.getLuminance(e);return(Math.max(s,n)+.05)/(Math.min(s,n)+.05)}hexToRgb(t){const e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null}rgbToHex(t){return"#"+(1<<24|t.r<<16|t.g<<8|t.b).toString(16).slice(1)}applyEventStyles(t){const e=this.getEventBaseCssStyle(t),s=Object.entries(e).map(([t,e])=>`${t}: ${e}`).join("; ");return s?`style="${s}"`:""}}
|