kalendly 0.3.0 → 0.3.2
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/README.md +155 -20
- package/dist/core/index.d.mts +16 -2
- package/dist/core/index.d.ts +16 -2
- package/dist/core/index.js +153 -5
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +142 -5
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.d.mts +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +297 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +286 -31
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +274 -30
- package/dist/index.umd.js.map +1 -1
- package/dist/styles/calendar.css +33 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,12 +43,76 @@ function generateYears(minYear, maxYear) {
|
|
|
43
43
|
const max = maxYear ?? currentYear + 10;
|
|
44
44
|
return Array.from({ length: max - min + 1 }, (_, i) => min + i);
|
|
45
45
|
}
|
|
46
|
-
function
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
function parseHourRanges(value, slotDuration) {
|
|
47
|
+
const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
48
|
+
if (parts.length === 0) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`<kal-calendar> available-hours is empty. Omit the attribute to allow every hour, or name at least one HH:MM-HH:MM range.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const ranges = parts.map((part) => {
|
|
54
|
+
const halves = part.split("-");
|
|
55
|
+
if (halves.length !== 2) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`<kal-calendar> available-hours range "${part}" is not HH:MM-HH:MM.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
const [start, end] = halves.map((half) => parseTimeToMinutes(half.trim()));
|
|
61
|
+
if (start === null || end === null) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`<kal-calendar> available-hours range "${part}" has an unreadable time. Use 24-hour HH:MM.`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (start >= end) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`<kal-calendar> available-hours range "${part}" starts at or after it ends.`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (start % slotDuration !== 0 || end % slotDuration !== 0) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`<kal-calendar> available-hours range "${part}" does not land on a ${slotDuration}-minute slot boundary.`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return [start, end];
|
|
51
77
|
});
|
|
78
|
+
if (mergeIntervals(ranges).length !== ranges.length) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`<kal-calendar> available-hours ranges overlap or touch: "${value}". Write each bookable window once.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return ranges;
|
|
84
|
+
}
|
|
85
|
+
function isDateWithinWindow(date, min, max) {
|
|
86
|
+
const target = normalizeDate(date).getTime();
|
|
87
|
+
if (min && target < normalizeDate(min).getTime()) return false;
|
|
88
|
+
if (max && target > normalizeDate(max).getTime()) return false;
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
function isDayAllowed(date, days) {
|
|
92
|
+
return days === null || days.includes(date.getDay());
|
|
93
|
+
}
|
|
94
|
+
function eventCoversDate(event, date) {
|
|
95
|
+
const start = normalizeDate(new Date(event.date)).getTime();
|
|
96
|
+
const target = normalizeDate(date).getTime();
|
|
97
|
+
if (Number.isNaN(start)) return false;
|
|
98
|
+
if (event.endDate === void 0 || event.endDate === null) {
|
|
99
|
+
return start === target;
|
|
100
|
+
}
|
|
101
|
+
const end = normalizeDate(new Date(event.endDate)).getTime();
|
|
102
|
+
if (Number.isNaN(end)) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`<kal-calendar> event ${event.id} has an unreadable endDate: ${String(event.endDate)}.`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (end < start) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`<kal-calendar> event ${event.id} has an endDate before its date: ${String(event.endDate)} < ${String(event.date)}.`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return target >= start && target <= end;
|
|
113
|
+
}
|
|
114
|
+
function getEventsForDate(events, date) {
|
|
115
|
+
return events.filter((event) => eventCoversDate(event, date));
|
|
52
116
|
}
|
|
53
117
|
function hasEvents(events, date) {
|
|
54
118
|
return getEventsForDate(events, date).length > 0;
|
|
@@ -192,7 +256,67 @@ function safeColor(value) {
|
|
|
192
256
|
const trimmed = String(value).trim();
|
|
193
257
|
return isValidHexColor(trimmed) || /^[a-z]+$/i.test(trimmed) ? trimmed : "#3b82f6";
|
|
194
258
|
}
|
|
195
|
-
|
|
259
|
+
function parseTimeToMinutes(time) {
|
|
260
|
+
if (typeof time !== "string") return null;
|
|
261
|
+
const match = /^(\d{1,2}):(\d{2})$/.exec(time.trim());
|
|
262
|
+
if (!match) return null;
|
|
263
|
+
const hours = Number(match[1]);
|
|
264
|
+
const mins = Number(match[2]);
|
|
265
|
+
if (hours > 24 || mins > 59 || hours === 24 && mins > 0) return null;
|
|
266
|
+
return hours * 60 + mins;
|
|
267
|
+
}
|
|
268
|
+
function formatMinutes(total) {
|
|
269
|
+
const hours = Math.floor(total / 60);
|
|
270
|
+
const mins = total % 60;
|
|
271
|
+
return `${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
|
|
272
|
+
}
|
|
273
|
+
function eventInterval(event, slotDuration, onDay) {
|
|
274
|
+
const day = normalizeDate(onDay).getTime();
|
|
275
|
+
if (Number.isNaN(day)) return null;
|
|
276
|
+
const base = day / 6e4;
|
|
277
|
+
const wholeDay = [base, base + MINUTES_PER_DAY];
|
|
278
|
+
if (event.allDay || !event.startTime) return wholeDay;
|
|
279
|
+
const from = parseTimeToMinutes(event.startTime);
|
|
280
|
+
if (from === null) return wholeDay;
|
|
281
|
+
if (event.endTime === void 0 || event.endTime === null) {
|
|
282
|
+
return [base + from, base + from + slotDuration];
|
|
283
|
+
}
|
|
284
|
+
const to = parseTimeToMinutes(event.endTime);
|
|
285
|
+
if (to === null) return wholeDay;
|
|
286
|
+
return [base + from, base + (to <= from ? to + MINUTES_PER_DAY : to)];
|
|
287
|
+
}
|
|
288
|
+
function mergeIntervals(intervals) {
|
|
289
|
+
const sorted = [...intervals].sort((a, b) => a[0] - b[0]);
|
|
290
|
+
return sorted.reduce((merged, [start, end]) => {
|
|
291
|
+
const last = merged[merged.length - 1];
|
|
292
|
+
if (last && start <= last[1]) last[1] = Math.max(last[1], end);
|
|
293
|
+
else merged.push([start, end]);
|
|
294
|
+
return merged;
|
|
295
|
+
}, []);
|
|
296
|
+
}
|
|
297
|
+
function bookedSlots(events, date, slotDuration = DEFAULT_SLOT_DURATION) {
|
|
298
|
+
const base = normalizeDate(date).getTime() / 6e4;
|
|
299
|
+
const previousDay = new Date(date);
|
|
300
|
+
previousDay.setDate(previousDay.getDate() - 1);
|
|
301
|
+
const intervals = [];
|
|
302
|
+
for (const event of new Set(events)) {
|
|
303
|
+
for (const day of [previousDay, date]) {
|
|
304
|
+
if (!eventCoversDate(event, day)) continue;
|
|
305
|
+
const interval = eventInterval(event, slotDuration, day);
|
|
306
|
+
if (interval) intervals.push(interval);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const merged = mergeIntervals(intervals);
|
|
310
|
+
return Array.from(
|
|
311
|
+
{ length: Math.floor(MINUTES_PER_DAY / slotDuration) },
|
|
312
|
+
(_, index) => {
|
|
313
|
+
const start = base + index * slotDuration;
|
|
314
|
+
const end = start + slotDuration;
|
|
315
|
+
return merged.some(([from, to]) => start < to && end > from);
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
var MONTHS, MONTHS_FULL, DAYS, DEFAULT_CATEGORY_COLORS, HTML_ESCAPES, MINUTES_PER_DAY, DEFAULT_SLOT_DURATION;
|
|
196
320
|
var init_utils = __esm({
|
|
197
321
|
"src/core/utils.ts"() {
|
|
198
322
|
"use strict";
|
|
@@ -248,6 +372,8 @@ var init_utils = __esm({
|
|
|
248
372
|
'"': """,
|
|
249
373
|
"'": "'"
|
|
250
374
|
};
|
|
375
|
+
MINUTES_PER_DAY = 1440;
|
|
376
|
+
DEFAULT_SLOT_DURATION = 60;
|
|
251
377
|
}
|
|
252
378
|
});
|
|
253
379
|
|
|
@@ -661,6 +787,29 @@ var init_CalendarElement = __esm({
|
|
|
661
787
|
}
|
|
662
788
|
return title;
|
|
663
789
|
}
|
|
790
|
+
get slotDuration() {
|
|
791
|
+
const raw = this.getAttribute("slot-duration");
|
|
792
|
+
if (raw === null) return DEFAULT_SLOT_DURATION;
|
|
793
|
+
const minutes = Number(raw);
|
|
794
|
+
if (Number.isInteger(minutes) && minutes > 0 && MINUTES_PER_DAY % minutes === 0) {
|
|
795
|
+
return minutes;
|
|
796
|
+
}
|
|
797
|
+
console.warn(
|
|
798
|
+
`<kal-calendar> slot-duration="${raw}" must be a positive whole number of minutes that divides ${MINUTES_PER_DAY} \u2014 falling back to ${DEFAULT_SLOT_DURATION}.`
|
|
799
|
+
);
|
|
800
|
+
return DEFAULT_SLOT_DURATION;
|
|
801
|
+
}
|
|
802
|
+
warnMissingEndTime(events) {
|
|
803
|
+
for (const event of events) {
|
|
804
|
+
if (!event.startTime || event.endTime) continue;
|
|
805
|
+
const key = String(event.id);
|
|
806
|
+
if (_CalendarElement.warnedMissingEnd.has(key)) continue;
|
|
807
|
+
_CalendarElement.warnedMissingEnd.add(key);
|
|
808
|
+
console.warn(
|
|
809
|
+
`<kal-calendar> event ${key} has startTime but no endTime \u2014 occupying one ${this.slotDuration}-minute slot. Send an endTime to say how long it runs.`
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
664
813
|
get monthCount() {
|
|
665
814
|
const requested = Number(this.getAttribute("months") ?? 1);
|
|
666
815
|
if (!Number.isInteger(requested) || requested < 1) return 1;
|
|
@@ -674,6 +823,41 @@ var init_CalendarElement = __esm({
|
|
|
674
823
|
const val = this.getAttribute("max-year");
|
|
675
824
|
return val ? parseInt(val, 10) : (/* @__PURE__ */ new Date()).getFullYear() + 10;
|
|
676
825
|
}
|
|
826
|
+
boundaryDate(attr) {
|
|
827
|
+
const val = this.getAttribute(attr);
|
|
828
|
+
if (!val) return null;
|
|
829
|
+
const parsed = new Date(val);
|
|
830
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
831
|
+
throw new Error(
|
|
832
|
+
`<kal-calendar> ${attr} is unreadable: "${val}". Use a value Date can parse, the same as initial-date.`
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
return parsed;
|
|
836
|
+
}
|
|
837
|
+
get availableDays() {
|
|
838
|
+
const val = this.getAttribute("available-days");
|
|
839
|
+
if (val === null) return null;
|
|
840
|
+
const parts = val.split(",").map((part) => part.trim()).filter(Boolean);
|
|
841
|
+
if (parts.length === 0) {
|
|
842
|
+
throw new Error(
|
|
843
|
+
`<kal-calendar> available-days is empty. Omit the attribute to allow every day, or name at least one weekday.`
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
return parts.map((part) => {
|
|
847
|
+
const day = Number(part);
|
|
848
|
+
if (!Number.isInteger(day) || day < 0 || day > 6) {
|
|
849
|
+
throw new Error(
|
|
850
|
+
`<kal-calendar> available-days must list integers 0-6, 0 = Sunday. Got "${part}".`
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
return day;
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
get availableHours() {
|
|
857
|
+
const val = this.getAttribute("available-hours");
|
|
858
|
+
if (val === null) return null;
|
|
859
|
+
return parseHourRanges(val, this.slotDuration);
|
|
860
|
+
}
|
|
677
861
|
initEngine() {
|
|
678
862
|
const initialDateAttr = this.getAttribute("initial-date");
|
|
679
863
|
const initialDate = initialDateAttr ? new Date(initialDateAttr) : void 0;
|
|
@@ -792,8 +976,26 @@ var init_CalendarElement = __esm({
|
|
|
792
976
|
if (declared.size === 0) return "open";
|
|
793
977
|
return this.knownBuckets.find((bucket) => declared.has(bucket));
|
|
794
978
|
}
|
|
979
|
+
assertHorizonOrdered() {
|
|
980
|
+
const min = this.boundaryDate("min-date");
|
|
981
|
+
const max = this.boundaryDate("max-date");
|
|
982
|
+
if (min && max && min.getTime() > max.getTime()) {
|
|
983
|
+
throw new Error(
|
|
984
|
+
`<kal-calendar> min-date is after max-date: "${this.getAttribute("min-date")}" > "${this.getAttribute("max-date")}".`
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
// Whether the vendor offers this day at all, before any event is considered.
|
|
989
|
+
isDateOffered(date) {
|
|
990
|
+
return isDateWithinWindow(
|
|
991
|
+
date,
|
|
992
|
+
this.boundaryDate("min-date"),
|
|
993
|
+
this.boundaryDate("max-date")
|
|
994
|
+
) && isDayAllowed(date, this.availableDays);
|
|
995
|
+
}
|
|
795
996
|
isDateSelectable(date) {
|
|
796
997
|
if (!this.engine) return false;
|
|
998
|
+
if (!this.isDateOffered(date)) return false;
|
|
797
999
|
if (this._selectableStatuses) {
|
|
798
1000
|
return this._selectableStatuses.includes(this.resolveBucket(date));
|
|
799
1001
|
}
|
|
@@ -813,6 +1015,11 @@ var init_CalendarElement = __esm({
|
|
|
813
1015
|
this.assertStatusesDeclared();
|
|
814
1016
|
this.assertStatusesKnown();
|
|
815
1017
|
}
|
|
1018
|
+
this.boundaryDate("min-date");
|
|
1019
|
+
this.boundaryDate("max-date");
|
|
1020
|
+
void this.availableDays;
|
|
1021
|
+
void this.availableHours;
|
|
1022
|
+
this.assertHorizonOrdered();
|
|
816
1023
|
const today = /* @__PURE__ */ new Date();
|
|
817
1024
|
const todayMonth = today.getMonth();
|
|
818
1025
|
const todayYear = today.getFullYear();
|
|
@@ -856,7 +1063,7 @@ var init_CalendarElement = __esm({
|
|
|
856
1063
|
return `
|
|
857
1064
|
<div class="event-card" style="border-left-color: ${borderColor}">
|
|
858
1065
|
<div class="event-header">
|
|
859
|
-
|
|
1066
|
+
${event.name ? `<div class="event-title">${escapeHtml(event.name)}</div>` : ""}
|
|
860
1067
|
<div class="event-badges">
|
|
861
1068
|
${event.category ? `<span class="badge category category-${slugifyToken(event.category)}">${escapeHtml(getCategoryLabel(event.category))}</span>` : ""}
|
|
862
1069
|
${event.priority ? `<span class="badge priority priority-${slugifyToken(event.priority)}">${escapeHtml(getPriorityLabel(event.priority))}</span>` : ""}
|
|
@@ -922,42 +1129,45 @@ var init_CalendarElement = __esm({
|
|
|
922
1129
|
const defaultRenderNoEvents = () => '<div class="no-events-message">No events scheduled for this day.</div>';
|
|
923
1130
|
const renderEvent = this._renderEvent || defaultRenderEvent;
|
|
924
1131
|
const renderNoEvents = this._renderNoEvents || defaultRenderNoEvents;
|
|
925
|
-
const renderTimeGrid = (
|
|
926
|
-
const
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
const startTime =
|
|
940
|
-
const endTime =
|
|
941
|
-
const
|
|
942
|
-
const inTimeRange = !
|
|
1132
|
+
const renderTimeGrid = (date) => {
|
|
1133
|
+
const slotDuration = this.slotDuration;
|
|
1134
|
+
const previousDay = new Date(date);
|
|
1135
|
+
previousDay.setDate(previousDay.getDate() - 1);
|
|
1136
|
+
const events = [
|
|
1137
|
+
...this.engine.getEventsForDate(previousDay),
|
|
1138
|
+
...this.engine.getEventsForDate(date)
|
|
1139
|
+
];
|
|
1140
|
+
this.warnMissingEndTime(events);
|
|
1141
|
+
const booked = bookedSlots(events, date, slotDuration);
|
|
1142
|
+
const hours = this.availableHours;
|
|
1143
|
+
const slots = booked.map((isBooked, index) => {
|
|
1144
|
+
const slotStart = index * slotDuration;
|
|
1145
|
+
const slotEnd = slotStart + slotDuration;
|
|
1146
|
+
const startTime = formatMinutes(slotStart);
|
|
1147
|
+
const endTime = formatMinutes(slotEnd);
|
|
1148
|
+
const offered = hours === null || hours.some(([from, to]) => slotStart >= from && slotEnd <= to);
|
|
1149
|
+
const inTimeRange = offered && !isBooked && selectable && this._timeRangeStart !== null && this._timeRangeEnd !== null && isSameDay2(this._timeRangeDate, date) && startTime >= this._timeRangeStart && endTime <= this._timeRangeEnd;
|
|
943
1150
|
const isRangeStart = inTimeRange && startTime === this._timeRangeStart;
|
|
944
1151
|
const isRangeEnd = inTimeRange && endTime === this._timeRangeEnd;
|
|
945
1152
|
const isInRange = inTimeRange && !isRangeStart && !isRangeEnd;
|
|
946
1153
|
const slotClasses = [
|
|
947
1154
|
"time-grid-slot",
|
|
948
|
-
|
|
1155
|
+
offered ? "" : "time-grid-slot-out-of-range",
|
|
1156
|
+
isBooked ? "time-grid-slot-blocked" : "time-grid-slot-open",
|
|
949
1157
|
isRangeStart ? "time-grid-slot-range-start" : "",
|
|
950
1158
|
isRangeEnd ? "time-grid-slot-range-end" : "",
|
|
951
1159
|
isInRange ? "time-grid-slot-in-range" : ""
|
|
952
1160
|
].filter(Boolean).join(" ");
|
|
953
|
-
const slotAttrs =
|
|
1161
|
+
const slotAttrs = `${offered ? 'data-action="select-slot" ' : ""}data-start-time="${startTime}" data-end-time="${endTime}" data-date="${date.toISOString()}" data-booked="${isBooked}"`;
|
|
1162
|
+
const status = !offered ? "Closed" : isBooked ? "Booked" : "Available";
|
|
954
1163
|
return `
|
|
955
1164
|
<div class="${slotClasses}" ${slotAttrs}>
|
|
956
1165
|
<span class="time-grid-label">${startTime}</span>
|
|
957
|
-
<span class="time-grid-status">${
|
|
1166
|
+
<span class="time-grid-status">${status}</span>
|
|
958
1167
|
</div>`;
|
|
959
1168
|
});
|
|
960
|
-
|
|
1169
|
+
const gridClasses = selectable ? "time-grid time-grid-selectable" : "time-grid";
|
|
1170
|
+
return `<div class="${gridClasses}">${slots.join("")}</div>`;
|
|
961
1171
|
};
|
|
962
1172
|
const multiMonth = viewModel.panes.length > 1;
|
|
963
1173
|
const renderPane = (pane) => `
|
|
@@ -982,6 +1192,12 @@ var init_CalendarElement = __esm({
|
|
|
982
1192
|
${week.map((calendarDate, dayIndex) => {
|
|
983
1193
|
const classes = getCellClasses(calendarDate);
|
|
984
1194
|
const cellAttrs = [];
|
|
1195
|
+
if (viewModel.selectedDate && isSameDay2(
|
|
1196
|
+
calendarDate.date,
|
|
1197
|
+
viewModel.selectedDate
|
|
1198
|
+
)) {
|
|
1199
|
+
classes.push("calendar-cell-selected");
|
|
1200
|
+
}
|
|
985
1201
|
if (availabilityMode && calendarDate.isCurrentMonth) {
|
|
986
1202
|
const bucket = this.resolveBucket(
|
|
987
1203
|
calendarDate.date
|
|
@@ -1015,12 +1231,18 @@ var init_CalendarElement = __esm({
|
|
|
1015
1231
|
}
|
|
1016
1232
|
}
|
|
1017
1233
|
const dateString = calendarDate.date.toISOString();
|
|
1234
|
+
const offered = this.isDateOffered(
|
|
1235
|
+
calendarDate.date
|
|
1236
|
+
);
|
|
1237
|
+
if (!offered) {
|
|
1238
|
+
classes.push("calendar-cell-out-of-range");
|
|
1239
|
+
}
|
|
1018
1240
|
return `
|
|
1019
1241
|
<td
|
|
1020
1242
|
class="${classes.join(" ")}"
|
|
1021
1243
|
data-date="${dateString}"
|
|
1022
1244
|
data-day-index="${dayIndex}"
|
|
1023
|
-
data-clickable="true"
|
|
1245
|
+
${offered ? 'data-clickable="true"' : ""}
|
|
1024
1246
|
${cellAttrs.join(" ")}
|
|
1025
1247
|
>
|
|
1026
1248
|
${calendarDate.date.getDate()}
|
|
@@ -1134,7 +1356,7 @@ var init_CalendarElement = __esm({
|
|
|
1134
1356
|
` : ""}
|
|
1135
1357
|
|
|
1136
1358
|
<div class="events-container">
|
|
1137
|
-
${availabilityMode === "time" ? renderTimeGrid(viewModel.
|
|
1359
|
+
${availabilityMode === "time" ? renderTimeGrid(viewModel.selectedDate) : viewModel.tasks.length > 0 ? viewModel.tasks.map((event) => renderEvent(event)).join("") : renderNoEvents()}
|
|
1138
1360
|
</div>
|
|
1139
1361
|
</div>
|
|
1140
1362
|
` : ""}
|
|
@@ -1295,6 +1517,20 @@ var init_CalendarElement = __esm({
|
|
|
1295
1517
|
const slotStart = actionEl.dataset.startTime;
|
|
1296
1518
|
const slotEnd = actionEl.dataset.endTime;
|
|
1297
1519
|
const slotDate = new Date(actionEl.dataset.date);
|
|
1520
|
+
const slotBooked = actionEl.dataset.booked === "true";
|
|
1521
|
+
this.dispatchEvent(
|
|
1522
|
+
new CustomEvent("cal-slot-select", {
|
|
1523
|
+
bubbles: true,
|
|
1524
|
+
composed: true,
|
|
1525
|
+
detail: {
|
|
1526
|
+
date: slotDate,
|
|
1527
|
+
startTime: slotStart,
|
|
1528
|
+
endTime: slotEnd,
|
|
1529
|
+
booked: slotBooked
|
|
1530
|
+
}
|
|
1531
|
+
})
|
|
1532
|
+
);
|
|
1533
|
+
if (slotBooked || !this.hasAttribute("selectable")) break;
|
|
1298
1534
|
if (this._timeRangeComplete) {
|
|
1299
1535
|
this._timeRangeDate = slotDate;
|
|
1300
1536
|
this._timeRangeStart = slotStart;
|
|
@@ -1432,9 +1668,14 @@ var init_CalendarElement = __esm({
|
|
|
1432
1668
|
"initial-date",
|
|
1433
1669
|
"min-year",
|
|
1434
1670
|
"max-year",
|
|
1671
|
+
"min-date",
|
|
1672
|
+
"max-date",
|
|
1673
|
+
"available-days",
|
|
1674
|
+
"available-hours",
|
|
1435
1675
|
"week-starts-on",
|
|
1436
1676
|
"heading",
|
|
1437
1677
|
"months",
|
|
1678
|
+
"slot-duration",
|
|
1438
1679
|
"title",
|
|
1439
1680
|
"use-short-month-names",
|
|
1440
1681
|
"availability-mode",
|
|
@@ -1452,6 +1693,8 @@ var init_CalendarElement = __esm({
|
|
|
1452
1693
|
borderColor: "--calendar-border-color",
|
|
1453
1694
|
todayOutline: "--calendar-today-outline",
|
|
1454
1695
|
selectedBg: "--calendar-selected-bg",
|
|
1696
|
+
outOfRangeBg: "--calendar-out-of-range-bg",
|
|
1697
|
+
outOfRangeFg: "--calendar-out-of-range-fg",
|
|
1455
1698
|
headerBg: "--calendar-header-bg",
|
|
1456
1699
|
popupBg: "--calendar-popup-bg",
|
|
1457
1700
|
pickerBg: "--calendar-picker-bg",
|
|
@@ -1486,6 +1729,7 @@ var init_CalendarElement = __esm({
|
|
|
1486
1729
|
badgeTentativeBg: "--calendar-badge-tentative-bg",
|
|
1487
1730
|
badgeTentativeText: "--calendar-badge-tentative-text"
|
|
1488
1731
|
};
|
|
1732
|
+
_CalendarElement.warnedMissingEnd = /* @__PURE__ */ new Set();
|
|
1489
1733
|
_CalendarElement.BUILT_IN_BUCKETS = ["blocked", "conditional", "open"];
|
|
1490
1734
|
_CalendarElement.titleDeprecationWarned = false;
|
|
1491
1735
|
CalendarElement = _CalendarElement;
|
|
@@ -1499,12 +1743,18 @@ __export(web_components_exports, {
|
|
|
1499
1743
|
CalendarEngine: () => CalendarEngine,
|
|
1500
1744
|
DAYS: () => DAYS,
|
|
1501
1745
|
DEFAULT_CATEGORY_COLORS: () => DEFAULT_CATEGORY_COLORS,
|
|
1746
|
+
DEFAULT_SLOT_DURATION: () => DEFAULT_SLOT_DURATION,
|
|
1747
|
+
MINUTES_PER_DAY: () => MINUTES_PER_DAY,
|
|
1502
1748
|
MONTHS: () => MONTHS,
|
|
1503
1749
|
MONTHS_FULL: () => MONTHS_FULL,
|
|
1750
|
+
bookedSlots: () => bookedSlots,
|
|
1504
1751
|
defineCalendarElement: () => defineCalendarElement,
|
|
1505
1752
|
escapeHtml: () => escapeHtml,
|
|
1753
|
+
eventCoversDate: () => eventCoversDate,
|
|
1754
|
+
eventInterval: () => eventInterval,
|
|
1506
1755
|
formatAttendees: () => formatAttendees,
|
|
1507
1756
|
formatDateForDisplay: () => formatDateForDisplay,
|
|
1757
|
+
formatMinutes: () => formatMinutes,
|
|
1508
1758
|
formatTimeRange: () => formatTimeRange,
|
|
1509
1759
|
generateCalendarDates: () => generateCalendarDates,
|
|
1510
1760
|
generateYears: () => generateYears,
|
|
@@ -1514,11 +1764,16 @@ __export(web_components_exports, {
|
|
|
1514
1764
|
getEventsForDate: () => getEventsForDate,
|
|
1515
1765
|
getMonthYearText: () => getMonthYearText,
|
|
1516
1766
|
hasEvents: () => hasEvents,
|
|
1767
|
+
isDateWithinWindow: () => isDateWithinWindow,
|
|
1768
|
+
isDayAllowed: () => isDayAllowed,
|
|
1517
1769
|
isSameDay: () => isSameDay,
|
|
1518
1770
|
isToday: () => isToday,
|
|
1519
1771
|
isValidHexColor: () => isValidHexColor,
|
|
1520
1772
|
mergeCategoryColors: () => mergeCategoryColors,
|
|
1773
|
+
mergeIntervals: () => mergeIntervals,
|
|
1521
1774
|
normalizeDate: () => normalizeDate,
|
|
1775
|
+
parseHourRanges: () => parseHourRanges,
|
|
1776
|
+
parseTimeToMinutes: () => parseTimeToMinutes,
|
|
1522
1777
|
safeColor: () => safeColor,
|
|
1523
1778
|
safeUrl: () => safeUrl,
|
|
1524
1779
|
slugifyToken: () => slugifyToken,
|
|
@@ -1540,12 +1795,18 @@ if (typeof customElements !== "undefined" && !customElements.get("kal-calendar")
|
|
|
1540
1795
|
CalendarEngine,
|
|
1541
1796
|
DAYS,
|
|
1542
1797
|
DEFAULT_CATEGORY_COLORS,
|
|
1798
|
+
DEFAULT_SLOT_DURATION,
|
|
1799
|
+
MINUTES_PER_DAY,
|
|
1543
1800
|
MONTHS,
|
|
1544
1801
|
MONTHS_FULL,
|
|
1802
|
+
bookedSlots,
|
|
1545
1803
|
defineCalendarElement,
|
|
1546
1804
|
escapeHtml,
|
|
1805
|
+
eventCoversDate,
|
|
1806
|
+
eventInterval,
|
|
1547
1807
|
formatAttendees,
|
|
1548
1808
|
formatDateForDisplay,
|
|
1809
|
+
formatMinutes,
|
|
1549
1810
|
formatTimeRange,
|
|
1550
1811
|
generateCalendarDates,
|
|
1551
1812
|
generateYears,
|
|
@@ -1555,11 +1816,16 @@ if (typeof customElements !== "undefined" && !customElements.get("kal-calendar")
|
|
|
1555
1816
|
getEventsForDate,
|
|
1556
1817
|
getMonthYearText,
|
|
1557
1818
|
hasEvents,
|
|
1819
|
+
isDateWithinWindow,
|
|
1820
|
+
isDayAllowed,
|
|
1558
1821
|
isSameDay,
|
|
1559
1822
|
isToday,
|
|
1560
1823
|
isValidHexColor,
|
|
1561
1824
|
mergeCategoryColors,
|
|
1825
|
+
mergeIntervals,
|
|
1562
1826
|
normalizeDate,
|
|
1827
|
+
parseHourRanges,
|
|
1828
|
+
parseTimeToMinutes,
|
|
1563
1829
|
safeColor,
|
|
1564
1830
|
safeUrl,
|
|
1565
1831
|
slugifyToken,
|