@mantine-vue/schedule 2.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.
Files changed (104) hide show
  1. package/README.md +21 -0
  2. package/cjs/index.cjs +4198 -0
  3. package/cjs/index.cjs.map +1 -0
  4. package/esm/index.mjs +4106 -0
  5. package/esm/index.mjs.map +1 -0
  6. package/lib/component-props.d.ts +265 -0
  7. package/lib/components/CurrentTimeIndicator/CurrentTimeIndicator.d.ts +114 -0
  8. package/lib/components/CurrentTimeIndicator/index.d.ts +1 -0
  9. package/lib/components/DayView/DayView.d.ts +212 -0
  10. package/lib/components/DayView/get-day-view-events/get-day-positioned-events.d.ts +15 -0
  11. package/lib/components/DayView/get-day-view-events/get-day-view-events.d.ts +15 -0
  12. package/lib/components/DayView/index.d.ts +3 -0
  13. package/lib/components/DragContext/DragContext.d.ts +11 -0
  14. package/lib/components/DragContext/index.d.ts +1 -0
  15. package/lib/components/MobileMonthView/MobileMonthView.d.ts +171 -0
  16. package/lib/components/MobileMonthView/get-mobile-month-view-events.d.ts +8 -0
  17. package/lib/components/MobileMonthView/index.d.ts +1 -0
  18. package/lib/components/MonthView/MonthView.d.ts +174 -0
  19. package/lib/components/MonthView/get-month-view-events/add-event-to-day-groups.d.ts +14 -0
  20. package/lib/components/MonthView/get-month-view-events/calculate-event-position-in-week.d.ts +18 -0
  21. package/lib/components/MonthView/get-month-view-events/find-available-row.d.ts +10 -0
  22. package/lib/components/MonthView/get-month-view-events/get-month-positioned-events.d.ts +31 -0
  23. package/lib/components/MonthView/get-month-view-events/get-month-view-events.d.ts +16 -0
  24. package/lib/components/MonthView/get-month-view-events/get-weeks-in-range.d.ts +13 -0
  25. package/lib/components/MonthView/get-renderable-month-event-segments.d.ts +16 -0
  26. package/lib/components/MonthView/index.d.ts +4 -0
  27. package/lib/components/MoreEvents/MoreEvents.d.ts +65 -0
  28. package/lib/components/MoreEvents/index.d.ts +1 -0
  29. package/lib/components/Schedule/Schedule.d.ts +134 -0
  30. package/lib/components/Schedule/index.d.ts +1 -0
  31. package/lib/components/ScheduleEvent/ScheduleEvent.d.ts +88 -0
  32. package/lib/components/ScheduleEvent/index.d.ts +1 -0
  33. package/lib/components/ScheduleHeader/HeaderControl/index.d.ts +2 -0
  34. package/lib/components/ScheduleHeader/MonthYearSelect/index.d.ts +2 -0
  35. package/lib/components/ScheduleHeader/ScheduleHeader.d.ts +364 -0
  36. package/lib/components/ScheduleHeader/ScheduleHeaderBase.d.ts +72 -0
  37. package/lib/components/ScheduleHeader/ViewSelect/index.d.ts +2 -0
  38. package/lib/components/ScheduleHeader/index.d.ts +2 -0
  39. package/lib/components/WeekView/WeekView.d.ts +294 -0
  40. package/lib/components/WeekView/get-week-label/get-week-label.d.ts +13 -0
  41. package/lib/components/WeekView/get-week-view-events/assign-event-rows.d.ts +2 -0
  42. package/lib/components/WeekView/get-week-view-events/calculate-all-day-event-offset.d.ts +11 -0
  43. package/lib/components/WeekView/get-week-view-events/calculate-all-day-event-width.d.ts +12 -0
  44. package/lib/components/WeekView/get-week-view-events/calculate-event-days.d.ts +9 -0
  45. package/lib/components/WeekView/get-week-view-events/calculate-regular-event-overlaps.d.ts +2 -0
  46. package/lib/components/WeekView/get-week-view-events/filter-week-view-events.d.ts +14 -0
  47. package/lib/components/WeekView/get-week-view-events/find-available-column.d.ts +9 -0
  48. package/lib/components/WeekView/get-week-view-events/get-event-end-date.d.ts +3 -0
  49. package/lib/components/WeekView/get-week-view-events/get-hanging-status.d.ts +9 -0
  50. package/lib/components/WeekView/get-week-view-events/get-week-positioned-events.d.ts +26 -0
  51. package/lib/components/WeekView/get-week-view-events/get-week-view-events.d.ts +7 -0
  52. package/lib/components/WeekView/index.d.ts +4 -0
  53. package/lib/components/YearView/YearView.d.ts +151 -0
  54. package/lib/components/YearView/get-year-view-events/get-year-view-events.d.ts +8 -0
  55. package/lib/components/YearView/index.d.ts +1 -0
  56. package/lib/components/keyboard-navigation.d.ts +7 -0
  57. package/lib/components/shared.d.ts +161 -0
  58. package/lib/components/use-slot-drag-select.d.ts +28 -0
  59. package/lib/hooks/use-event-resize.d.ts +31 -0
  60. package/lib/index.d.mts +15 -0
  61. package/lib/index.d.ts +15 -0
  62. package/lib/labels.d.ts +25 -0
  63. package/lib/test-utils.d.ts +7 -0
  64. package/lib/types.d.ts +141 -0
  65. package/lib/utils/calculate-drop-time/calculate-drop-time.d.ts +22 -0
  66. package/lib/utils/calculate-month-drop-date/calculate-month-drop-date.d.ts +14 -0
  67. package/lib/utils/clamp-interval-minutes/clamp-interval-minutes.d.ts +2 -0
  68. package/lib/utils/expand-recurring-events/expand-recurring-events.d.ts +10 -0
  69. package/lib/utils/format-date/format-date.d.ts +8 -0
  70. package/lib/utils/get-business-hours-mod/get-business-hours-mod.d.ts +26 -0
  71. package/lib/utils/get-current-time-position/get-current-time-position.d.ts +10 -0
  72. package/lib/utils/get-day-position/get-day-position.d.ts +17 -0
  73. package/lib/utils/get-day-time-intervals/get-day-time-intervals.d.ts +19 -0
  74. package/lib/utils/get-end-of-week/get-end-of-week.d.ts +3 -0
  75. package/lib/utils/get-month-days/get-month-days.d.ts +8 -0
  76. package/lib/utils/get-month-range/get-month-range.d.ts +13 -0
  77. package/lib/utils/get-months-by-quarter/get-months-by-quarter.d.ts +2 -0
  78. package/lib/utils/get-months-list/get-months-list.d.ts +11 -0
  79. package/lib/utils/get-start-of-week/get-start-of-week.d.ts +7 -0
  80. package/lib/utils/get-visible-events/get-visible-events.d.ts +9 -0
  81. package/lib/utils/get-week-days/get-week-days.d.ts +13 -0
  82. package/lib/utils/get-week-number/get-week-number.d.ts +2 -0
  83. package/lib/utils/get-weekdays-names/get-weekdays-names.d.ts +9 -0
  84. package/lib/utils/get-years-list/get-years-list.d.ts +6 -0
  85. package/lib/utils/index.d.ts +41 -0
  86. package/lib/utils/is-after-min-date/is-after-min-date.d.ts +2 -0
  87. package/lib/utils/is-all-day-event/is-all-day-event.d.ts +7 -0
  88. package/lib/utils/is-before-max-date/is-before-max-date.d.ts +2 -0
  89. package/lib/utils/is-event-in-time-range/is-event-in-time-range.d.ts +8 -0
  90. package/lib/utils/is-events-overlap/is-events-overlap.d.ts +3 -0
  91. package/lib/utils/is-in-time-range/is-in-time-range.d.ts +9 -0
  92. package/lib/utils/is-multiday-event/is-multiday-event.d.ts +2 -0
  93. package/lib/utils/is-same-month/is-same-month.d.ts +2 -0
  94. package/lib/utils/is-within-week/is-within-week.d.ts +8 -0
  95. package/lib/utils/next-week/next-week.d.ts +2 -0
  96. package/lib/utils/parse-time-string/parse-time-string.d.ts +6 -0
  97. package/lib/utils/previous-week/previous-week.d.ts +2 -0
  98. package/lib/utils/sort-events/sort-events.d.ts +3 -0
  99. package/lib/utils/to-date-string/to-date-string.d.ts +2 -0
  100. package/lib/utils/to-time-string/to-time-string.d.ts +2 -0
  101. package/lib/utils/validate-event/validate-event.d.ts +2 -0
  102. package/package.json +53 -0
  103. package/styles.css +2087 -0
  104. package/styles.layer.css +2089 -0
package/esm/index.mjs ADDED
@@ -0,0 +1,4106 @@
1
+ import dayjs from "dayjs";
2
+ import isoWeek from "dayjs/plugin/isoWeek.js";
3
+ import * as rruleAll from "rrule";
4
+ import { defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref, watch } from "vue";
5
+ import { AccordionChevron, Box, Modal, NativeSelect, Popover, ScrollArea, Text, UnstyledButton, createScopedKeydownHandler, getThemeColor, useDirection, useSafeMantineTheme } from "@mantine-vue/core";
6
+ //#region src/labels.ts
7
+ var DEFAULT_SCHEDULE_LABELS = {
8
+ today: "Today",
9
+ next: "Next",
10
+ previous: "Previous",
11
+ more: "More",
12
+ day: "Day",
13
+ week: "Week",
14
+ month: "Month",
15
+ year: "Year",
16
+ allDay: "All day",
17
+ weekday: "Weekday",
18
+ timeSlot: "Time slot",
19
+ selectMonth: "Select month",
20
+ selectYear: "Select year",
21
+ switchToDayView: "Switch to day view",
22
+ switchToWeekView: "Switch to week view",
23
+ switchToMonthView: "Switch to month view",
24
+ switchToYearView: "Switch to year view",
25
+ viewSelectLabel: "Calendar view",
26
+ noEvents: "No events",
27
+ moreLabel: (hiddenEventsCount) => `+${hiddenEventsCount} more`
28
+ };
29
+ function getLabel(key, override) {
30
+ if (override) return {
31
+ ...DEFAULT_SCHEDULE_LABELS,
32
+ ...override
33
+ }[key];
34
+ return DEFAULT_SCHEDULE_LABELS[key];
35
+ }
36
+ //#endregion
37
+ //#region src/utils/format-date/format-date.ts
38
+ function formatDate({ locale, date, format }) {
39
+ if (typeof format === "function") return format(dayjs(date).format("YYYY-MM-DD HH:mm:ss"));
40
+ return dayjs(date).locale(locale).format(format);
41
+ }
42
+ //#endregion
43
+ //#region src/utils/get-weekdays-names/get-weekdays-names.ts
44
+ function getWeekdaysNames({ locale, format = "dd", firstDayOfWeek = 1 }) {
45
+ const baseDate = dayjs().day(firstDayOfWeek);
46
+ const labels = [];
47
+ for (let i = 0; i < 7; i += 1) labels.push(formatDate({
48
+ locale,
49
+ date: baseDate.add(i, "days"),
50
+ format
51
+ }));
52
+ return labels;
53
+ }
54
+ //#endregion
55
+ //#region src/utils/get-start-of-week/get-start-of-week.ts
56
+ function getStartOfWeek({ date, firstDayOfWeek = 1 }) {
57
+ let value = dayjs(date);
58
+ while (value.day() !== firstDayOfWeek) value = value.subtract(1, "day");
59
+ return value.format("YYYY-MM-DD");
60
+ }
61
+ //#endregion
62
+ //#region src/utils/get-end-of-week/get-end-of-week.ts
63
+ function getEndOfWeek(date, firstDayOfWeek = 1) {
64
+ let value = dayjs(date);
65
+ if (!value.isValid()) return value;
66
+ const lastDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1;
67
+ while (value.day() !== lastDayOfWeek) value = value.add(1, "day");
68
+ return value.format("YYYY-MM-DD");
69
+ }
70
+ //#endregion
71
+ //#region src/utils/get-week-number/get-week-number.ts
72
+ dayjs.extend(isoWeek);
73
+ function getWeekNumber(week) {
74
+ if (Array.isArray(week)) return dayjs(week.find((date) => dayjs(date).day() === 1)).isoWeek();
75
+ return dayjs(week).isoWeek();
76
+ }
77
+ //#endregion
78
+ //#region src/utils/get-month-days/get-month-days.ts
79
+ function getMonthDays({ month, firstDayOfWeek = 1, consistentWeeks }) {
80
+ const start = dayjs(dayjs(month).subtract(dayjs(month).date() - 1, "day").format("YYYY-MM-DD"));
81
+ const startOfMonth = start.format("YYYY-MM-DD");
82
+ const endDate = getEndOfWeek(start.add(+start.daysInMonth() - 1, "day").format("YYYY-MM-DD"), firstDayOfWeek);
83
+ const weeks = [];
84
+ let date = dayjs(getStartOfWeek({
85
+ date: startOfMonth,
86
+ firstDayOfWeek
87
+ }));
88
+ while (dayjs(date).isBefore(endDate, "day")) {
89
+ const days = [];
90
+ for (let i = 0; i < 7; i += 1) {
91
+ days.push(date.format("YYYY-MM-DD 00:00:00"));
92
+ date = date.add(1, "day");
93
+ }
94
+ weeks.push(days);
95
+ }
96
+ if (consistentWeeks && weeks.length < 6) {
97
+ const lastWeek = weeks[weeks.length - 1];
98
+ const lastDay = lastWeek[lastWeek.length - 1];
99
+ let nextDay = dayjs(lastDay).add(1, "day");
100
+ while (weeks.length < 6) {
101
+ const days = [];
102
+ for (let i = 0; i < 7; i += 1) {
103
+ days.push(nextDay.format("YYYY-MM-DD 00:00:00"));
104
+ nextDay = nextDay.add(1, "day");
105
+ }
106
+ weeks.push(days);
107
+ }
108
+ }
109
+ return weeks;
110
+ }
111
+ //#endregion
112
+ //#region src/utils/is-after-min-date/is-after-min-date.ts
113
+ function isAfterMinDate(date, minDate) {
114
+ return minDate ? dayjs(date).isAfter(dayjs(minDate).subtract(1, "day"), "day") : true;
115
+ }
116
+ //#endregion
117
+ //#region src/utils/is-before-max-date/is-before-max-date.ts
118
+ function isBeforeMaxDate(date, maxDate) {
119
+ return maxDate ? dayjs(date).isBefore(dayjs(maxDate).add(1, "day"), "day") : true;
120
+ }
121
+ //#endregion
122
+ //#region src/utils/is-same-month/is-same-month.ts
123
+ function isSameMonth(date, comparison) {
124
+ return dayjs(date).format("YYYY-MM") === dayjs(comparison).format("YYYY-MM");
125
+ }
126
+ //#endregion
127
+ //#region src/utils/get-months-by-quarter/get-months-by-quarter.ts
128
+ function getMonthsByQuarter(year) {
129
+ const startOfYear = dayjs(year).startOf("year").toDate();
130
+ const results = [
131
+ [],
132
+ [],
133
+ [],
134
+ []
135
+ ];
136
+ let currentMonthIndex = 0;
137
+ for (let i = 0; i < 4; i += 1) for (let j = 0; j < 3; j += 1) {
138
+ results[i].push(dayjs(startOfYear).add(currentMonthIndex, "months").format("YYYY-MM-DD"));
139
+ currentMonthIndex += 1;
140
+ }
141
+ return results;
142
+ }
143
+ //#endregion
144
+ //#region src/utils/clamp-interval-minutes/clamp-interval-minutes.ts
145
+ /** Clamp interval minutes to valid values (1-60) and ensure it divides evenly into 60 */
146
+ function clampIntervalMinutes(intervalMinutes) {
147
+ let clamped = Math.round(Math.max(1, Math.min(60, intervalMinutes)));
148
+ clamped = 60 % clamped === 0 ? clamped : 60;
149
+ return clamped;
150
+ }
151
+ //#endregion
152
+ //#region src/utils/parse-time-string/parse-time-string.ts
153
+ function parseTimeString(time) {
154
+ const [hours, minutes, seconds] = time.split(":").map(Number);
155
+ return {
156
+ hours,
157
+ minutes,
158
+ seconds: seconds || 0
159
+ };
160
+ }
161
+ //#endregion
162
+ //#region src/utils/to-time-string/to-time-string.ts
163
+ function toTimeString({ hours, minutes, seconds }) {
164
+ return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
165
+ }
166
+ //#endregion
167
+ //#region src/utils/get-day-time-intervals/get-day-time-intervals.ts
168
+ function getDayTimeIntervals({ startTime, endTime, intervalMinutes: _intervalMinutes = 60 }) {
169
+ const intervalMinutes = clampIntervalMinutes(_intervalMinutes);
170
+ const start = parseTimeString(startTime);
171
+ const end = endTime ? parseTimeString(endTime) : {
172
+ hours: 23,
173
+ minutes: 59,
174
+ seconds: 59
175
+ };
176
+ const startSeconds = start.hours * 3600 + start.minutes * 60 + start.seconds;
177
+ const endSeconds = end.hours * 3600 + end.minutes * 60 + end.seconds;
178
+ const intervalSeconds = intervalMinutes * 60;
179
+ const intervals = [];
180
+ let currentSeconds = startSeconds;
181
+ while (currentSeconds < endSeconds) {
182
+ const intervalStartSeconds = currentSeconds;
183
+ let intervalEndSeconds = currentSeconds + intervalSeconds;
184
+ if (intervalEndSeconds > endSeconds) intervalEndSeconds = endSeconds;
185
+ const startHours = Math.floor(intervalStartSeconds / 3600);
186
+ const startMinutes = Math.floor(intervalStartSeconds % 3600 / 60);
187
+ const startSecs = intervalStartSeconds % 60;
188
+ const endHours = Math.floor(intervalEndSeconds / 3600);
189
+ const endMinutes = Math.floor(intervalEndSeconds % 3600 / 60);
190
+ const endSecs = intervalEndSeconds % 60;
191
+ const durationSeconds = intervalEndSeconds - intervalStartSeconds;
192
+ const isHourStart = startMinutes === 0 && startSecs === 0;
193
+ intervals.push({
194
+ startTime: toTimeString({
195
+ hours: startHours,
196
+ minutes: startMinutes,
197
+ seconds: startSecs
198
+ }),
199
+ endTime: toTimeString({
200
+ hours: endHours,
201
+ minutes: endMinutes,
202
+ seconds: endSecs
203
+ }),
204
+ duration: durationSeconds,
205
+ isHourStart
206
+ });
207
+ currentSeconds = intervalEndSeconds;
208
+ }
209
+ return intervals;
210
+ }
211
+ //#endregion
212
+ //#region src/utils/to-date-string/to-date-string.ts
213
+ function toDateString(date) {
214
+ return dayjs(date).format("YYYY-MM-DD 00:00:00");
215
+ }
216
+ //#endregion
217
+ //#region src/utils/get-week-days/get-week-days.ts
218
+ /** Returns a list of days in a given week */
219
+ function getWeekDays({ week, weekendDays, withWeekendDays = true, firstDayOfWeek = 1 }) {
220
+ const days = [];
221
+ let current = dayjs(getStartOfWeek({
222
+ date: week,
223
+ firstDayOfWeek
224
+ }));
225
+ for (let i = 0; i < 7; i += 1) {
226
+ const dayOfWeek = current.day();
227
+ if (!(weekendDays && weekendDays.includes(dayOfWeek)) || withWeekendDays) days.push(toDateString(current));
228
+ current = current.add(1, "day");
229
+ }
230
+ return days;
231
+ }
232
+ //#endregion
233
+ //#region src/utils/get-months-list/get-months-list.ts
234
+ function getMonthsList({ locale, format }) {
235
+ const months = [];
236
+ const date = dayjs().locale(locale).startOf("year");
237
+ for (let i = 0; i < 12; i++) months.push({
238
+ month: i,
239
+ name: formatDate({
240
+ date: date.add(i, "month"),
241
+ format,
242
+ locale
243
+ })
244
+ });
245
+ return months;
246
+ }
247
+ //#endregion
248
+ //#region src/utils/get-years-list/get-years-list.ts
249
+ function getYearsList({ startYear, endYear }) {
250
+ const years = [];
251
+ for (let year = startYear; year <= endYear; year++) years.push(year);
252
+ return years;
253
+ }
254
+ //#endregion
255
+ //#region src/utils/next-week/next-week.ts
256
+ function nextWeek(date, firstDayOfWeek) {
257
+ const start = getStartOfWeek({
258
+ date,
259
+ firstDayOfWeek
260
+ });
261
+ return toDateString(dayjs(start).set("date", dayjs(start).date() + 7));
262
+ }
263
+ //#endregion
264
+ //#region src/utils/previous-week/previous-week.ts
265
+ function previousWeek(date, firstDayOfWeek) {
266
+ const start = getStartOfWeek({
267
+ date,
268
+ firstDayOfWeek
269
+ });
270
+ return toDateString(dayjs(start).set("date", dayjs(start).date() - 7));
271
+ }
272
+ //#endregion
273
+ //#region src/utils/get-current-time-position/get-current-time-position.ts
274
+ function getCurrentTimePosition(input) {
275
+ const now = dayjs(input?.now);
276
+ if (!input?.startTime || !input?.endTime) {
277
+ const startOf = now.startOf("date");
278
+ return now.diff(startOf, "minute") / 1440 * 100;
279
+ }
280
+ const [startHour, startMinute, startSecond = 0] = input.startTime.split(":").map(Number);
281
+ const [endHour, endMinute, endSecond = 0] = input.endTime.split(":").map(Number);
282
+ const startOfDay = now.startOf("date");
283
+ const startDateTime = startOfDay.hour(startHour).minute(startMinute).second(startSecond);
284
+ const literalSeconds = startOfDay.hour(endHour).minute(endMinute).second(endSecond).diff(startDateTime, "second");
285
+ const intervalSeconds = input.intervalMinutes !== void 0 ? clampIntervalMinutes(input.intervalMinutes) * 60 : void 0;
286
+ const totalSeconds = intervalSeconds ? Math.ceil(literalSeconds / intervalSeconds) * intervalSeconds : literalSeconds;
287
+ return now.diff(startDateTime, "second") / totalSeconds * 100;
288
+ }
289
+ //#endregion
290
+ //#region src/utils/is-in-time-range/is-in-time-range.ts
291
+ /** Returns true if the given date's time is within the specified time range */
292
+ function isInTimeRange({ date, startTime = "00:00:00", endTime = "23:59:59" }) {
293
+ const targetDate = dayjs(date);
294
+ const parsedStartTime = parseTimeString(startTime);
295
+ const parsedEndTime = parseTimeString(endTime);
296
+ const startDateTime = targetDate.hour(parsedStartTime.hours).minute(parsedStartTime.minutes).second(parsedStartTime.seconds);
297
+ const endDateTime = targetDate.hour(parsedEndTime.hours).minute(parsedEndTime.minutes).second(parsedEndTime.seconds);
298
+ return targetDate.isAfter(startDateTime) && targetDate.isBefore(endDateTime);
299
+ }
300
+ //#endregion
301
+ //#region src/utils/is-all-day-event/is-all-day-event.ts
302
+ function isAllDayEvent({ event, date }) {
303
+ const dayStart = dayjs(date).startOf("day");
304
+ const nextDayStart = dayStart.add(1, "day");
305
+ const sameDayEnd = nextDayStart.subtract(1, "second");
306
+ const startTime = dayjs(event.start);
307
+ const endTime = dayjs(event.end);
308
+ return startTime.isSame(dayStart) && (endTime.isSame(nextDayStart) || endTime.isSame(sameDayEnd));
309
+ }
310
+ //#endregion
311
+ //#region src/utils/validate-event/validate-event.ts
312
+ function validateEvent(eventData) {
313
+ if (!dayjs(eventData.start).isValid()) throw new Error(`[@mantine/schedule] Invalid start date for event id: ${eventData.id}`);
314
+ if (!dayjs(eventData.end).isValid()) throw new Error(`[@mantine/schedule] Invalid end date for event id: ${eventData.id}`);
315
+ if (dayjs(eventData.end).isBefore(dayjs(eventData.start))) throw new Error(`[@mantine/schedule] Event end date is before start date for event id: ${eventData.id}`);
316
+ return eventData;
317
+ }
318
+ //#endregion
319
+ //#region src/utils/sort-events/sort-events.ts
320
+ /** Sorts events by start time, then by duration (longer first) */
321
+ function sortEvents(events) {
322
+ return [...events].sort((a, b) => {
323
+ const startDiff = dayjs(a.start).diff(dayjs(b.start));
324
+ if (startDiff !== 0) return startDiff;
325
+ return dayjs(b.end).diff(dayjs(b.start)) - dayjs(a.end).diff(dayjs(a.start));
326
+ });
327
+ }
328
+ //#endregion
329
+ //#region src/utils/is-events-overlap/is-events-overlap.ts
330
+ /** Returns true if two events overlap in time */
331
+ function isEventsOverlap(event1, event2) {
332
+ const start1 = dayjs(event1.start).valueOf();
333
+ const end1 = dayjs(event1.end).valueOf();
334
+ const start2 = dayjs(event2.start).valueOf();
335
+ return start1 < dayjs(event2.end).valueOf() && start2 < end1;
336
+ }
337
+ //#endregion
338
+ //#region src/utils/get-visible-events/get-visible-events.ts
339
+ function getVisibleEvents({ maxEvents, totalEvents }) {
340
+ if (totalEvents <= maxEvents) return {
341
+ visibleEventsCount: totalEvents,
342
+ hiddenEventsCount: 0
343
+ };
344
+ return {
345
+ visibleEventsCount: maxEvents - 1,
346
+ hiddenEventsCount: totalEvents - (maxEvents - 1)
347
+ };
348
+ }
349
+ //#endregion
350
+ //#region src/utils/is-multiday-event/is-multiday-event.ts
351
+ function isMultidayEvent(event) {
352
+ const startDate = dayjs(event.start).startOf("day");
353
+ const rawEnd = dayjs(event.end);
354
+ return (rawEnd.hour() === 0 && rawEnd.minute() === 0 && rawEnd.second() === 0 ? rawEnd.startOf("day").subtract(1, "day") : rawEnd.startOf("day")).isAfter(startDate);
355
+ }
356
+ //#endregion
357
+ //#region src/utils/is-event-in-time-range/is-event-in-time-range.ts
358
+ function spansFullDay(event) {
359
+ const start = dayjs(event.start);
360
+ const end = dayjs(event.end);
361
+ if (!start.isSame(start.startOf("day"))) return false;
362
+ const nextDayStart = start.startOf("day").add(1, "day");
363
+ return end.isSame(nextDayStart) || end.isSame(nextDayStart.subtract(1, "second"));
364
+ }
365
+ function isEventInTimeRange({ event, startTime, endTime }) {
366
+ if (isMultidayEvent(event) || spansFullDay(event)) return true;
367
+ if (!startTime || !endTime) return true;
368
+ const [startHour, startMinute] = startTime.split(":").map(Number);
369
+ const [endHour, endMinute] = endTime.split(":").map(Number);
370
+ const timeWindowStartMinutes = startHour * 60 + startMinute;
371
+ const timeWindowEndMinutes = endHour * 60 + endMinute;
372
+ const eventStart = dayjs(event.start);
373
+ const eventEnd = dayjs(event.end);
374
+ const eventStartMinutes = eventStart.hour() * 60 + eventStart.minute();
375
+ return !(eventEnd.hour() * 60 + eventEnd.minute() <= timeWindowStartMinutes || eventStartMinutes >= timeWindowEndMinutes);
376
+ }
377
+ //#endregion
378
+ //#region src/utils/is-within-week/is-within-week.ts
379
+ function isWithinWeek({ event, targetWeek, firstDayOfWeek }) {
380
+ const startOfWeek = dayjs(getStartOfWeek({
381
+ date: targetWeek,
382
+ firstDayOfWeek
383
+ }));
384
+ const endOfWeek = startOfWeek.add(7, "day");
385
+ return dayjs(event.start).isBefore(endOfWeek) && dayjs(event.end).isAfter(startOfWeek);
386
+ }
387
+ //#endregion
388
+ //#region src/utils/get-month-range/get-month-range.ts
389
+ /** Returns start and end dates as displayed in MonthView */
390
+ function getMonthRange({ month, withOutsideDays, consistentWeeks, firstDayOfWeek }) {
391
+ if (!withOutsideDays) return {
392
+ start: toDateString(dayjs(month).startOf("month")),
393
+ end: toDateString(dayjs(month).endOf("month"))
394
+ };
395
+ const days = getMonthDays({
396
+ month,
397
+ firstDayOfWeek,
398
+ consistentWeeks
399
+ });
400
+ return {
401
+ start: days[0][0],
402
+ end: days[days.length - 1][6]
403
+ };
404
+ }
405
+ //#endregion
406
+ //#region src/utils/get-day-position/get-day-position.ts
407
+ /** Calculates day position within given start and end time boundaries. Returns top and height in percentages. */
408
+ function getDayPosition({ event, startTime = "00:00:00", endTime = "23:59:59", intervalMinutes = 60 }) {
409
+ const eventStart = dayjs(event.start);
410
+ const eventEnd = dayjs(event.end);
411
+ const parsedStartTime = parseTimeString(startTime);
412
+ const parsedEndTime = parseTimeString(endTime);
413
+ const startOfDay = eventStart.startOf("date");
414
+ const boundaryStart = startOfDay.hour(parsedStartTime.hours).minute(parsedStartTime.minutes).second(parsedStartTime.seconds);
415
+ const literalEnd = startOfDay.hour(parsedEndTime.hours).minute(parsedEndTime.minutes).second(parsedEndTime.seconds);
416
+ const intervalSeconds = clampIntervalMinutes(intervalMinutes) * 60;
417
+ const literalRangeSeconds = literalEnd.diff(boundaryStart, "second");
418
+ const totalSeconds = Math.ceil(literalRangeSeconds / intervalSeconds) * intervalSeconds;
419
+ const eventStartSeconds = (eventStart.isBefore(boundaryStart) ? boundaryStart : eventStart).diff(boundaryStart, "second");
420
+ const eventEndSeconds = (eventEnd.isAfter(literalEnd) ? literalEnd : eventEnd).diff(boundaryStart, "second");
421
+ const startPercent = eventStartSeconds / totalSeconds * 100;
422
+ return {
423
+ top: startPercent,
424
+ height: eventEndSeconds / totalSeconds * 100 - startPercent
425
+ };
426
+ }
427
+ //#endregion
428
+ //#region src/utils/calculate-drop-time/calculate-drop-time.ts
429
+ function calculateDropTime({ draggedEvent, targetDate, targetSlotTime, mouseYOffset = 0, slotHeight = 64, intervalMinutes = 15 }) {
430
+ const eventDuration = dayjs(draggedEvent.end).diff(dayjs(draggedEvent.start), "millisecond");
431
+ const parsedTime = parseTimeString(targetSlotTime);
432
+ const baseTargetTime = dayjs(targetDate).startOf("day").hour(parsedTime.hours).minute(parsedTime.minutes).second(0);
433
+ let finalTargetTime = baseTargetTime;
434
+ if (mouseYOffset > 0 && slotHeight > 0) {
435
+ const offsetRatio = mouseYOffset / slotHeight;
436
+ const offsetMinutes = Math.round(offsetRatio * intervalMinutes);
437
+ finalTargetTime = baseTargetTime.add(offsetMinutes, "minute");
438
+ }
439
+ return {
440
+ start: finalTargetTime.toDate(),
441
+ end: finalTargetTime.add(eventDuration, "millisecond").toDate()
442
+ };
443
+ }
444
+ //#endregion
445
+ //#region src/utils/calculate-month-drop-date/calculate-month-drop-date.ts
446
+ function calculateMonthDropDate({ draggedEvent, targetDay }) {
447
+ const eventDuration = dayjs(draggedEvent.end).diff(dayjs(draggedEvent.start), "millisecond");
448
+ const originalStartTime = dayjs(draggedEvent.start);
449
+ const newStart = dayjs(targetDay).startOf("day").hour(originalStartTime.hour()).minute(originalStartTime.minute()).second(originalStartTime.second()).millisecond(originalStartTime.millisecond());
450
+ const newEnd = newStart.add(eventDuration, "millisecond");
451
+ return {
452
+ start: newStart.toDate(),
453
+ end: newEnd.toDate()
454
+ };
455
+ }
456
+ //#endregion
457
+ //#region src/utils/get-business-hours-mod/get-business-hours-mod.ts
458
+ function isBusinessHoursRange(value) {
459
+ return Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "string";
460
+ }
461
+ /**
462
+ * Determines if a given time is within business hours and returns modifier object
463
+ * @param time - Time string in HH:mm:ss format
464
+ * @param businessHours - Tuple of [start, end] times in HH:mm:ss format, or per-day record keyed by day of the week
465
+ * @param highlightBusinessHours - Whether to highlight business hours
466
+ * @param dayOfWeek - Day of the week (0 – Sunday, 6 – Saturday), used to resolve per-day business hours
467
+ * @returns Modifier object for styling business/non-business hours
468
+ */
469
+ function getBusinessHoursMod({ time, businessHours, highlightBusinessHours, dayOfWeek }) {
470
+ if (!highlightBusinessHours || !businessHours) return {
471
+ "business-hours": false,
472
+ "non-business-hours": false
473
+ };
474
+ let range;
475
+ if (isBusinessHoursRange(businessHours)) range = businessHours;
476
+ else {
477
+ if (dayOfWeek === void 0) return {
478
+ "business-hours": false,
479
+ "non-business-hours": false
480
+ };
481
+ range = businessHours[dayOfWeek] ?? null;
482
+ }
483
+ if (!range) return {
484
+ "business-hours": false,
485
+ "non-business-hours": true
486
+ };
487
+ const [start, end] = range;
488
+ const isInBusinessHours = time >= start && time < end;
489
+ return {
490
+ "business-hours": isInBusinessHours,
491
+ "non-business-hours": !isInBusinessHours
492
+ };
493
+ }
494
+ //#endregion
495
+ //#region src/utils/expand-recurring-events/expand-recurring-events.ts
496
+ function resolveRRule(ns) {
497
+ return (ns.default ?? ns).RRule;
498
+ }
499
+ var RRule = resolveRRule(rruleAll);
500
+ function getRecurrenceKey(recurringEventId, recurrenceId) {
501
+ return `${recurringEventId}::${recurrenceId}`;
502
+ }
503
+ function overlapsRange(eventStart, eventEnd, rangeStart, rangeEnd) {
504
+ return (eventEnd.isAfter(rangeStart) || eventEnd.isSame(rangeStart)) && (eventStart.isBefore(rangeEnd) || eventStart.isSame(rangeEnd));
505
+ }
506
+ function getExdateSet(recurrence) {
507
+ if (!recurrence?.exdate) return /* @__PURE__ */ new Set();
508
+ const values = recurrence.exdate.map((value) => dayjs(value)).filter((value) => value.isValid()).map((value) => value.format("YYYY-MM-DD HH:mm:ss"));
509
+ return new Set(values);
510
+ }
511
+ function getRRuleString(rule) {
512
+ const normalized = rule.trim();
513
+ if (!normalized.includes("\n")) return normalized.startsWith("RRULE:") ? normalized.replace(/^RRULE:/, "") : normalized;
514
+ const rruleLine = normalized.split("\n").map((line) => line.trim()).find((line) => line.startsWith("RRULE:"));
515
+ return rruleLine ? rruleLine.replace(/^RRULE:/, "") : normalized;
516
+ }
517
+ function getOccurrenceStartsInRange(event, rangeStart, rangeEnd, expansionLimit, durationMs) {
518
+ const dtstart = dayjs(event.recurrence?.dtstart || event.start);
519
+ if (!dtstart.isValid() || !event.recurrence) return [];
520
+ try {
521
+ const options = RRule.parseString(getRRuleString(event.recurrence.rrule));
522
+ options.dtstart = dtstart.toDate();
523
+ const rule = new RRule(options);
524
+ const searchStart = rangeStart.subtract(Math.max(0, durationMs), "millisecond").toDate();
525
+ return rule.between(searchStart, rangeEnd.toDate(), true).slice(0, expansionLimit).map((value) => dayjs(value));
526
+ } catch {
527
+ return [];
528
+ }
529
+ }
530
+ function isEventInRange(event, rangeStart, rangeEnd) {
531
+ const start = dayjs(event.start);
532
+ const end = dayjs(event.end);
533
+ if (!start.isValid() || !end.isValid()) return false;
534
+ return overlapsRange(start, end, rangeStart, rangeEnd);
535
+ }
536
+ function createGeneratedInstance(event, occurrenceStart, durationMs) {
537
+ const occurrenceEnd = occurrenceStart.add(durationMs, "millisecond");
538
+ const recurrenceId = occurrenceStart.format("YYYY-MM-DD HH:mm:ss");
539
+ const { recurrence: _recurrence, ...eventWithoutRecurrence } = event;
540
+ return {
541
+ ...eventWithoutRecurrence,
542
+ id: `${event.id}::${recurrenceId}`,
543
+ start: occurrenceStart.format("YYYY-MM-DD HH:mm:ss"),
544
+ end: occurrenceEnd.format("YYYY-MM-DD HH:mm:ss"),
545
+ recurringEventId: event.id,
546
+ recurrenceId,
547
+ recurringInstance: {
548
+ isRecurringInstance: true,
549
+ recurringEventId: event.id,
550
+ recurrenceId,
551
+ originalStart: occurrenceStart.format("YYYY-MM-DD HH:mm:ss"),
552
+ originalEnd: occurrenceEnd.format("YYYY-MM-DD HH:mm:ss")
553
+ }
554
+ };
555
+ }
556
+ var DEFAULT_EXPANSION_LIMIT = 2e3;
557
+ function expandRecurringEvents({ events, rangeStart, rangeEnd, expansionLimit = DEFAULT_EXPANSION_LIMIT }) {
558
+ if (!events || events.length === 0) return [];
559
+ const start = dayjs(rangeStart);
560
+ const end = dayjs(rangeEnd);
561
+ if (!start.isValid() || !end.isValid()) return [];
562
+ const regularEvents = [];
563
+ const recurringEvents = [];
564
+ const overrides = /* @__PURE__ */ new Map();
565
+ for (const event of events) {
566
+ if (event.recurringEventId && event.recurrenceId) {
567
+ overrides.set(getRecurrenceKey(event.recurringEventId, event.recurrenceId), event);
568
+ continue;
569
+ }
570
+ if (event.recurrence?.rrule) {
571
+ recurringEvents.push(event);
572
+ continue;
573
+ }
574
+ regularEvents.push(event);
575
+ }
576
+ const output = [];
577
+ const consumedOverrideIds = /* @__PURE__ */ new Set();
578
+ for (const event of regularEvents) if (isEventInRange(event, start, end)) output.push(validateEvent(event));
579
+ for (const event of recurringEvents) {
580
+ const eventStart = dayjs(event.recurrence?.dtstart || event.start);
581
+ const eventEnd = dayjs(event.end);
582
+ if (!eventStart.isValid() || !eventEnd.isValid()) continue;
583
+ const durationMs = eventEnd.diff(dayjs(event.start), "millisecond");
584
+ if (durationMs < 0) continue;
585
+ const exdate = getExdateSet(event.recurrence);
586
+ const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);
587
+ for (const occurrenceStart of starts) {
588
+ const recurrenceId = occurrenceStart.format("YYYY-MM-DD HH:mm:ss");
589
+ if (exdate.has(recurrenceId)) continue;
590
+ const overrideKey = getRecurrenceKey(event.id, recurrenceId);
591
+ const override = overrides.get(overrideKey);
592
+ if (override) {
593
+ if (isEventInRange(override, start, end)) {
594
+ output.push(validateEvent(override));
595
+ consumedOverrideIds.add(override.id);
596
+ }
597
+ continue;
598
+ }
599
+ const generated = createGeneratedInstance(event, occurrenceStart, durationMs);
600
+ if (overlapsRange(dayjs(generated.start), dayjs(generated.end), start, end)) output.push(validateEvent(generated));
601
+ }
602
+ }
603
+ for (const override of overrides.values()) {
604
+ if (consumedOverrideIds.has(override.id)) continue;
605
+ if (isEventInRange(override, start, end)) output.push(validateEvent(override));
606
+ }
607
+ return output;
608
+ }
609
+ //#endregion
610
+ //#region src/hooks/use-event-resize.ts
611
+ function useEventResize(input) {
612
+ const resizeState = ref(null);
613
+ let justResized = false;
614
+ let savedUserSelect = null;
615
+ const clampAndSnap = (minutes, state) => {
616
+ const snapped = Math.round(minutes / state.intervalMinutes) * state.intervalMinutes;
617
+ return Math.max(0, Math.min(state.literalRange, snapped));
618
+ };
619
+ const snapPercent = (percent, state) => {
620
+ return clampAndSnap(percent / 100 * state.totalMinutes, state) / state.totalMinutes * 100;
621
+ };
622
+ const percentToDateTime = (percent, eventDate, state) => {
623
+ const minutes = percent / 100 * state.totalMinutes;
624
+ const totalMinutes = state.startMinutes + clampAndSnap(minutes, state);
625
+ const hours = Math.floor(totalMinutes / 60);
626
+ const mins = totalMinutes % 60;
627
+ return `${eventDate} ${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}:00`;
628
+ };
629
+ const handlePointerMove = (event) => {
630
+ const state = resizeState.value;
631
+ if (!state) return;
632
+ const containerRect = state.container.getBoundingClientRect();
633
+ if (containerRect.height === 0) return;
634
+ const relativeY = event.clientY - containerRect.top;
635
+ const snappedPercent = snapPercent(Math.max(0, Math.min(100, relativeY / containerRect.height * 100)), state);
636
+ let currentTop = state.originalTop;
637
+ let currentHeight = state.originalHeight;
638
+ if (state.edge === "bottom") currentHeight = Math.max(state.minHeightPercent, snappedPercent - state.originalTop);
639
+ else {
640
+ const originalBottom = state.originalTop + state.originalHeight;
641
+ currentTop = Math.min(snappedPercent, originalBottom - state.minHeightPercent);
642
+ currentHeight = originalBottom - currentTop;
643
+ }
644
+ resizeState.value = {
645
+ ...state,
646
+ currentTop,
647
+ currentHeight
648
+ };
649
+ };
650
+ const removeDocumentListeners = () => {
651
+ document.removeEventListener("pointermove", handlePointerMove);
652
+ document.removeEventListener("pointerup", handlePointerUp);
653
+ if (savedUserSelect !== null) {
654
+ document.body.style.userSelect = savedUserSelect;
655
+ savedUserSelect = null;
656
+ }
657
+ };
658
+ const handlePointerUp = () => {
659
+ const state = resizeState.value;
660
+ if (state && (state.currentTop !== state.originalTop || state.currentHeight !== state.originalHeight)) {
661
+ const newStart = state.edge === "top" ? percentToDateTime(state.currentTop, state.eventDate, state) : state.originalStart;
662
+ const newEnd = state.edge === "bottom" ? percentToDateTime(state.currentTop + state.currentHeight, state.eventDate, state) : state.originalEnd;
663
+ input.onEventResize()?.({
664
+ eventId: state.eventId,
665
+ newStart,
666
+ newEnd,
667
+ event: state.event
668
+ });
669
+ }
670
+ resizeState.value = null;
671
+ removeDocumentListeners();
672
+ justResized = true;
673
+ requestAnimationFrame(() => {
674
+ justResized = false;
675
+ });
676
+ };
677
+ const handleResizeStart = ({ event, edge, container, originalTop, originalHeight, eventDate, pointerEvent }) => {
678
+ if (!input.enabled() || input.mode() === "static") return;
679
+ pointerEvent.preventDefault();
680
+ pointerEvent.stopPropagation();
681
+ const parsedStartTime = parseTimeString(input.startTime());
682
+ const parsedEndTime = parseTimeString(input.endTime());
683
+ const startMinutes = parsedStartTime.hours * 60 + parsedStartTime.minutes;
684
+ const endMinutes = parsedEndTime.hours * 60 + parsedEndTime.minutes;
685
+ const intervalMinutes = clampIntervalMinutes(input.intervalMinutes());
686
+ const literalRange = endMinutes - startMinutes;
687
+ const totalMinutes = Math.ceil(literalRange / intervalMinutes) * intervalMinutes;
688
+ resizeState.value = {
689
+ eventId: event.id,
690
+ event,
691
+ edge,
692
+ container,
693
+ originalTop,
694
+ originalHeight,
695
+ currentTop: originalTop,
696
+ currentHeight: originalHeight,
697
+ eventDate,
698
+ originalStart: dayjs(event.start).format("YYYY-MM-DD HH:mm:ss"),
699
+ originalEnd: dayjs(event.end).format("YYYY-MM-DD HH:mm:ss"),
700
+ startMinutes,
701
+ literalRange,
702
+ totalMinutes,
703
+ intervalMinutes,
704
+ minHeightPercent: intervalMinutes / totalMinutes * 100
705
+ };
706
+ savedUserSelect = document.body.style.userSelect;
707
+ document.body.style.userSelect = "none";
708
+ document.addEventListener("pointermove", handlePointerMove);
709
+ document.addEventListener("pointerup", handlePointerUp);
710
+ };
711
+ const getResizePosition = (eventId) => {
712
+ const state = resizeState.value;
713
+ return state?.eventId === eventId ? {
714
+ top: state.currentTop,
715
+ height: state.currentHeight
716
+ } : null;
717
+ };
718
+ const isResizableEvent = (event) => input.enabled() && input.mode() !== "static" && event.display !== "background" && (input.canResizeEvent()?.(event) ?? true);
719
+ onBeforeUnmount(removeDocumentListeners);
720
+ return {
721
+ handleResizeStart,
722
+ getResizePosition,
723
+ isResizableEvent,
724
+ wasResizing: () => justResized
725
+ };
726
+ }
727
+ var CurrentTimeIndicator_module_default = {
728
+ currentTimeIndicator: "_currentTimeIndicator_v2g54_1",
729
+ currentTimeIndicatorLine: "_currentTimeIndicatorLine_v2g54_23",
730
+ currentTimeIndicatorThumb: "_currentTimeIndicatorThumb_v2g54_32",
731
+ currentTimeIndicatorTimeBubble: "_currentTimeIndicatorTimeBubble_v2g54_43"
732
+ };
733
+ //#endregion
734
+ //#region src/components/CurrentTimeIndicator/CurrentTimeIndicator.ts
735
+ var CurrentTimeIndicator = defineComponent({
736
+ name: "CurrentTimeIndicator",
737
+ inheritAttrs: false,
738
+ props: {
739
+ color: {
740
+ type: String,
741
+ default: "red"
742
+ },
743
+ startOffset: {
744
+ type: String,
745
+ default: "0px"
746
+ },
747
+ endOffset: {
748
+ type: String,
749
+ default: "0px"
750
+ },
751
+ topOffset: {
752
+ type: String,
753
+ default: "0px"
754
+ },
755
+ timeBubbleStartOffset: {
756
+ type: String,
757
+ default: "0px"
758
+ },
759
+ withTimeBubble: {
760
+ type: Boolean,
761
+ default: true
762
+ },
763
+ withThumb: {
764
+ type: Boolean,
765
+ default: true
766
+ },
767
+ currentTimeFormat: {
768
+ type: [String, Function],
769
+ default: "HH:mm"
770
+ },
771
+ locale: String,
772
+ startTime: {
773
+ type: String,
774
+ default: "00:00:00"
775
+ },
776
+ endTime: {
777
+ type: String,
778
+ default: "23:59:59"
779
+ },
780
+ intervalMinutes: {
781
+ type: Number,
782
+ default: 60
783
+ },
784
+ getCurrentTime: Function
785
+ },
786
+ setup(props, { attrs }) {
787
+ const theme = useSafeMantineTheme();
788
+ const tick = ref(0);
789
+ let timer;
790
+ onMounted(() => {
791
+ timer = setInterval(() => tick.value++, 3e4);
792
+ });
793
+ onBeforeUnmount(() => clearInterval(timer));
794
+ return () => {
795
+ tick.value;
796
+ const now = props.getCurrentTime?.() || dayjs();
797
+ if (!isInTimeRange({
798
+ date: now,
799
+ startTime: props.startTime,
800
+ endTime: props.endTime
801
+ })) return null;
802
+ const top = getCurrentTimePosition({
803
+ now,
804
+ startTime: props.startTime,
805
+ endTime: props.endTime,
806
+ intervalMinutes: props.intervalMinutes
807
+ });
808
+ const color = getThemeColor(props.color, theme.value);
809
+ const formattedTime = props.withTimeBubble ? formatDate({
810
+ date: now,
811
+ locale: props.locale || "en",
812
+ format: props.currentTimeFormat
813
+ }) : "";
814
+ return h(Box, {
815
+ ...attrs,
816
+ class: [CurrentTimeIndicator_module_default.currentTimeIndicator, attrs.class],
817
+ style: [{
818
+ "--indicator-color": color,
819
+ "--start-offset": props.startOffset,
820
+ "--end-offset": props.endOffset,
821
+ "--top-offset": `calc(${top}% + ${props.topOffset})`,
822
+ "--time-bubble-start-offset": props.timeBubbleStartOffset,
823
+ "--time-bubble-width": formattedTime.toString().toLowerCase().includes("m") ? "64px" : "46px"
824
+ }, attrs.style]
825
+ }, () => [
826
+ props.withTimeBubble ? h("div", { class: CurrentTimeIndicator_module_default.currentTimeIndicatorTimeBubble }, formattedTime) : null,
827
+ props.withThumb ? h("div", { class: CurrentTimeIndicator_module_default.currentTimeIndicatorThumb }) : null,
828
+ h("div", { class: CurrentTimeIndicator_module_default.currentTimeIndicatorLine })
829
+ ]);
830
+ };
831
+ }
832
+ });
833
+ var ScheduleEvent_module_default = {
834
+ event: "_event_bnqc2_1",
835
+ eventInner: "_eventInner_bnqc2_14",
836
+ eventResizeHandle: "_eventResizeHandle_bnqc2_177"
837
+ };
838
+ //#endregion
839
+ //#region src/components/ScheduleEvent/ScheduleEvent.ts
840
+ function resolveRadius$1(radius) {
841
+ if (radius == null) return void 0;
842
+ if (typeof radius === "number") return `${radius}px`;
843
+ return [
844
+ "xs",
845
+ "sm",
846
+ "md",
847
+ "lg",
848
+ "xl"
849
+ ].includes(radius) ? `var(--mantine-radius-${radius})` : radius;
850
+ }
851
+ var ScheduleEvent = defineComponent({
852
+ name: "ScheduleEvent",
853
+ inheritAttrs: false,
854
+ slots: Object,
855
+ props: {
856
+ event: {
857
+ type: Object,
858
+ required: true
859
+ },
860
+ radius: {
861
+ type: [String, Number],
862
+ default: "sm"
863
+ },
864
+ nowrap: Boolean,
865
+ autoSize: Boolean,
866
+ size: {
867
+ type: String,
868
+ default: "sm"
869
+ },
870
+ renderEventBody: Function,
871
+ renderEvent: Function,
872
+ hanging: String,
873
+ draggable: Boolean,
874
+ onEventDragStart: Function,
875
+ onEventDragEnd: Function,
876
+ isDragging: Boolean,
877
+ mode: {
878
+ type: String,
879
+ default: "default"
880
+ },
881
+ withResize: Boolean,
882
+ onResizeStart: Function,
883
+ isResizing: Boolean
884
+ },
885
+ setup(props, { attrs, slots }) {
886
+ const theme = useSafeMantineTheme();
887
+ const isNativeDragging = ref(false);
888
+ return () => {
889
+ const colors = theme.value.variantColorResolver({
890
+ color: props.event.color || theme.value.primaryColor,
891
+ theme: theme.value,
892
+ variant: props.event.variant || "light",
893
+ autoContrast: true
894
+ });
895
+ const body = props.renderEventBody?.(props.event) || slots.eventBody?.({ event: props.event }) || slots.default?.() || props.event.title;
896
+ const showResizeHandles = props.withResize && props.mode !== "static";
897
+ const rootProps = {
898
+ ...attrs,
899
+ class: [ScheduleEvent_module_default.event, attrs.class],
900
+ style: [{
901
+ "--event-color": colors.color,
902
+ "--event-bg": colors.background,
903
+ "--event-hover": colors.hover,
904
+ "--event-radius": resolveRadius$1(props.radius)
905
+ }, attrs.style],
906
+ "data-event-id": props.event.id,
907
+ title: props.event.title,
908
+ size: props.size,
909
+ mod: {
910
+ autoSize: props.autoSize,
911
+ hanging: props.hanging,
912
+ draggable: props.draggable,
913
+ dragging: props.isDragging || isNativeDragging.value,
914
+ static: props.mode === "static",
915
+ resizing: props.isResizing,
916
+ resizable: showResizeHandles
917
+ },
918
+ draggable: props.draggable && props.mode !== "static",
919
+ tabindex: props.mode === "static" ? -1 : 0,
920
+ onDragstart: (event) => {
921
+ if (!props.draggable || props.mode === "static") {
922
+ event.preventDefault();
923
+ return;
924
+ }
925
+ if (event.dataTransfer) {
926
+ event.dataTransfer.effectAllowed = "move";
927
+ event.dataTransfer.setData("application/json", JSON.stringify({ eventId: props.event.id }));
928
+ }
929
+ isNativeDragging.value = true;
930
+ props.onEventDragStart?.(props.event);
931
+ },
932
+ onDragend: props.mode === "static" ? void 0 : () => {
933
+ isNativeDragging.value = false;
934
+ props.onEventDragEnd?.();
935
+ },
936
+ onClick: props.mode === "static" ? void 0 : attrs.onClick
937
+ };
938
+ const children = [
939
+ showResizeHandles ? h(Box, {
940
+ class: ScheduleEvent_module_default.eventResizeHandle,
941
+ mod: { edge: "top" },
942
+ onPointerdown: (event) => props.onResizeStart?.("top", event)
943
+ }) : null,
944
+ h(Box, {
945
+ class: ScheduleEvent_module_default.eventInner,
946
+ mod: {
947
+ nowrap: props.nowrap,
948
+ size: props.size,
949
+ autoSize: props.autoSize,
950
+ hanging: props.hanging
951
+ }
952
+ }, () => body),
953
+ showResizeHandles ? h(Box, {
954
+ class: ScheduleEvent_module_default.eventResizeHandle,
955
+ mod: { edge: "bottom" },
956
+ onPointerdown: (event) => props.onResizeStart?.("bottom", event)
957
+ }) : null
958
+ ];
959
+ const renderProps = {
960
+ ...rootProps,
961
+ children
962
+ };
963
+ return props.renderEvent?.(props.event, renderProps) || slots.event?.({
964
+ ...renderProps,
965
+ event: props.event
966
+ }) || h(UnstyledButton, rootProps, () => children);
967
+ };
968
+ }
969
+ });
970
+ //#endregion
971
+ //#region src/components/shared.ts
972
+ var baseViewProps = {
973
+ date: {
974
+ type: [String, Date],
975
+ required: true
976
+ },
977
+ onDateChange: Function,
978
+ events: Array,
979
+ locale: String,
980
+ radius: [String, Number],
981
+ labels: Object,
982
+ mode: {
983
+ type: String,
984
+ default: "default"
985
+ },
986
+ withHeader: {
987
+ type: Boolean,
988
+ default: true
989
+ },
990
+ onViewChange: Function,
991
+ previousControlProps: Object,
992
+ nextControlProps: Object,
993
+ todayControlProps: Object,
994
+ viewSelectProps: Object,
995
+ renderEventBody: Function,
996
+ renderEvent: Function,
997
+ onEventClick: Function,
998
+ recurrenceExpansionLimit: {
999
+ type: Number,
1000
+ default: 2e3
1001
+ }
1002
+ };
1003
+ var timeViewProps = {
1004
+ ...baseViewProps,
1005
+ startTime: {
1006
+ type: String,
1007
+ default: "00:00:00"
1008
+ },
1009
+ endTime: {
1010
+ type: String,
1011
+ default: "23:59:59"
1012
+ },
1013
+ intervalMinutes: {
1014
+ type: Number,
1015
+ default: 60
1016
+ },
1017
+ slotLabelFormat: {
1018
+ type: [String, Function],
1019
+ default: "HH:mm"
1020
+ },
1021
+ withCurrentTimeIndicator: {
1022
+ type: Boolean,
1023
+ default: void 0
1024
+ },
1025
+ withCurrentTimeBubble: {
1026
+ type: Boolean,
1027
+ default: true
1028
+ },
1029
+ getCurrentTime: Function,
1030
+ slotHeight: {
1031
+ type: [String, Number],
1032
+ default: 64
1033
+ },
1034
+ highlightBusinessHours: Boolean,
1035
+ businessHours: [Array, Object],
1036
+ withEventsDragAndDrop: Boolean,
1037
+ onEventDrop: Function,
1038
+ canDragEvent: Function,
1039
+ onEventDragStart: Function,
1040
+ onEventDragEnd: Function,
1041
+ onTimeSlotClick: Function,
1042
+ onAllDaySlotClick: Function,
1043
+ withDragSlotSelect: Boolean,
1044
+ onSlotDragEnd: Function,
1045
+ startScrollTime: String,
1046
+ onExternalEventDrop: Function,
1047
+ withEventResize: Boolean,
1048
+ onEventResize: Function,
1049
+ canResizeEvent: Function
1050
+ };
1051
+ function resolveScheduleRadius(radius) {
1052
+ if (radius === void 0) return void 0;
1053
+ if (typeof radius === "number") return `${radius}px`;
1054
+ return [
1055
+ "xs",
1056
+ "sm",
1057
+ "md",
1058
+ "lg",
1059
+ "xl"
1060
+ ].includes(radius) ? `var(--mantine-radius-${radius})` : radius;
1061
+ }
1062
+ function getExpandedEvents(events, rangeStart, rangeEnd, expansionLimit) {
1063
+ return expandRecurringEvents({
1064
+ events,
1065
+ rangeStart,
1066
+ rangeEnd,
1067
+ expansionLimit
1068
+ });
1069
+ }
1070
+ /**
1071
+ * Build the slots object forwarded to a child component, omitting undefined entries.
1072
+ * Returns a `Record<string, unknown>` (possibly empty) so it satisfies Vue's `RawSlots`
1073
+ * type when passed as the third argument to `h()`.
1074
+ */
1075
+ function forwardEventSlots(slots) {
1076
+ const forwarded = {};
1077
+ if (slots?.eventBody) forwarded.eventBody = slots.eventBody;
1078
+ if (slots?.event) forwarded.event = slots.event;
1079
+ return forwarded;
1080
+ }
1081
+ function eventNode(event, props, extra = {}, slots) {
1082
+ const draggable = props.mode !== "static" && props.withEventsDragAndDrop === true && (props.canDragEvent?.(event) ?? true);
1083
+ return h(ScheduleEvent, {
1084
+ event,
1085
+ mode: props.mode ?? "default",
1086
+ renderEvent: props.renderEvent,
1087
+ renderEventBody: props.renderEventBody,
1088
+ draggable,
1089
+ onEventDragStart: props.onEventDragStart,
1090
+ onEventDragEnd: props.onEventDragEnd,
1091
+ onClick: (nativeEvent) => props.onEventClick?.(event, nativeEvent),
1092
+ ...extra
1093
+ }, forwardEventSlots(slots));
1094
+ }
1095
+ function getDropEvent(events, transfer) {
1096
+ const raw = transfer?.getData("application/json");
1097
+ if (!raw) return void 0;
1098
+ try {
1099
+ const data = JSON.parse(raw);
1100
+ if (typeof data !== "object" || data === null || !("eventId" in data)) return void 0;
1101
+ const eventId = data.eventId;
1102
+ if (typeof eventId !== "string" && typeof eventId !== "number") return void 0;
1103
+ return events?.find((event) => String(event.id) === String(eventId));
1104
+ } catch {
1105
+ return;
1106
+ }
1107
+ }
1108
+ function getTimeSlotDropTarget({ nativeEvent, container, intervals, date }) {
1109
+ const targetSlot = (nativeEvent.target instanceof Element ? nativeEvent.target : null)?.closest("[data-time-slot-index]");
1110
+ let slotIndex = targetSlot && container.contains(targetSlot) ? Number(targetSlot.dataset.timeSlotIndex) : NaN;
1111
+ if (!Number.isInteger(slotIndex)) {
1112
+ const slots = container.querySelectorAll("[data-time-slot-index]");
1113
+ slotIndex = Array.from(slots).findIndex((slot) => {
1114
+ const rect = slot.getBoundingClientRect();
1115
+ return nativeEvent.clientY >= rect.top && nativeEvent.clientY <= rect.bottom;
1116
+ });
1117
+ }
1118
+ const interval = intervals[slotIndex];
1119
+ return interval ? {
1120
+ slotIndex,
1121
+ target: `${date} ${interval.startTime}`
1122
+ } : void 0;
1123
+ }
1124
+ function moveEventTo(event, newStart) {
1125
+ const start = dayjs(event.start);
1126
+ const duration = dayjs(event.end).diff(start, "second");
1127
+ const nextStart = dayjs(newStart);
1128
+ return {
1129
+ eventId: event.id,
1130
+ newStart: nextStart.format("YYYY-MM-DD HH:mm:ss"),
1131
+ newEnd: nextStart.add(duration, "second").format("YYYY-MM-DD HH:mm:ss"),
1132
+ event
1133
+ };
1134
+ }
1135
+ function moveEventToAllDay(event, date) {
1136
+ const dayStart = dayjs(date).startOf("day");
1137
+ const spanDays = Math.max(1, dayjs(event.end).startOf("day").diff(dayjs(event.start).startOf("day"), "day"));
1138
+ return {
1139
+ eventId: event.id,
1140
+ newStart: dayStart.format("YYYY-MM-DD HH:mm:ss"),
1141
+ newEnd: dayStart.add(spanDays, "day").format("YYYY-MM-DD HH:mm:ss"),
1142
+ event
1143
+ };
1144
+ }
1145
+ var MoreEvents_module_default = {
1146
+ moreEventsButton: "_moreEventsButton_1irmu_1",
1147
+ moreEventsDropdown: "_moreEventsDropdown_1irmu_22",
1148
+ moreEventsList: "_moreEventsList_1irmu_26"
1149
+ };
1150
+ //#endregion
1151
+ //#region src/components/MoreEvents/MoreEvents.ts
1152
+ var MoreEvents = defineComponent({
1153
+ name: "MoreEvents",
1154
+ inheritAttrs: false,
1155
+ slots: Object,
1156
+ props: {
1157
+ events: {
1158
+ type: Array,
1159
+ required: true
1160
+ },
1161
+ moreEventsCount: {
1162
+ type: Number,
1163
+ required: true
1164
+ },
1165
+ radius: [String, Number],
1166
+ modalTitle: String,
1167
+ dropdownType: {
1168
+ type: String,
1169
+ default: "popover"
1170
+ },
1171
+ popoverProps: Object,
1172
+ modalProps: Object,
1173
+ onDropdownClose: Function,
1174
+ renderEventBody: Function,
1175
+ renderEvent: Function,
1176
+ labels: Object,
1177
+ mode: {
1178
+ type: String,
1179
+ default: "default"
1180
+ },
1181
+ onEventClick: Function
1182
+ },
1183
+ setup(props, { attrs, slots }) {
1184
+ const opened = ref(false);
1185
+ const close = () => {
1186
+ opened.value = false;
1187
+ props.onDropdownClose?.();
1188
+ };
1189
+ return () => {
1190
+ const eventsList = h(Box, { class: MoreEvents_module_default.moreEventsList }, () => props.events.map((event) => h(ScheduleEvent, {
1191
+ key: event.id,
1192
+ event,
1193
+ radius: props.radius ?? "sm",
1194
+ size: "md",
1195
+ mode: props.mode,
1196
+ renderEvent: props.renderEvent,
1197
+ renderEventBody: props.renderEventBody,
1198
+ onClick: (nativeEvent) => props.onEventClick?.(event, nativeEvent)
1199
+ }, forwardEventSlots(slots))));
1200
+ return [props.dropdownType === "modal" ? h(Modal, {
1201
+ ...props.modalProps,
1202
+ opened: opened.value,
1203
+ onClose: close,
1204
+ radius: props.radius,
1205
+ title: props.modalTitle
1206
+ }, () => eventsList) : null, h(Popover, {
1207
+ position: "bottom-start",
1208
+ width: 260,
1209
+ opened: opened.value,
1210
+ trapFocus: true,
1211
+ returnFocus: false,
1212
+ disabled: props.dropdownType === "modal",
1213
+ radius: props.radius,
1214
+ transitionProps: {
1215
+ transition: "pop",
1216
+ duration: 120
1217
+ },
1218
+ offset: -46,
1219
+ ...props.popoverProps,
1220
+ onChange: (value) => {
1221
+ if (!value) close();
1222
+ }
1223
+ }, () => [h(Popover.Target, null, () => h(UnstyledButton, {
1224
+ ...attrs,
1225
+ class: [MoreEvents_module_default.moreEventsButton, attrs.class],
1226
+ mod: { static: props.mode === "static" },
1227
+ "aria-expanded": opened.value,
1228
+ onClick: () => {
1229
+ opened.value = !opened.value;
1230
+ }
1231
+ }, () => getLabel("moreLabel", props.labels)(props.moreEventsCount))), h(Popover.Dropdown, { class: MoreEvents_module_default.moreEventsDropdown }, () => eventsList)])];
1232
+ };
1233
+ }
1234
+ });
1235
+ //#endregion
1236
+ //#region src/components/use-slot-drag-select.ts
1237
+ /**
1238
+ * Composable that provides unified slot drag-selection for Day, Week and Month views.
1239
+ * tracks a selected range as the pointer
1240
+ * moves across elements carrying `data-drag-slot-index` / `data-drag-slot-group`.
1241
+ */
1242
+ function useSlotDragSelect(input) {
1243
+ const selectedRange = ref(null);
1244
+ let drag = null;
1245
+ let savedUserSelect = "";
1246
+ const handlePointerMove = (event) => {
1247
+ if (!drag) return;
1248
+ const elements = document.elementsFromPoint(event.clientX, event.clientY);
1249
+ for (const el of elements) {
1250
+ const element = el;
1251
+ const indexAttr = element.getAttribute?.("data-drag-slot-index");
1252
+ const groupAttr = element.getAttribute?.("data-drag-slot-group");
1253
+ if (indexAttr != null && groupAttr != null) {
1254
+ if (groupAttr === drag.group) {
1255
+ const newIndex = Number(indexAttr);
1256
+ if (!Number.isNaN(newIndex) && newIndex !== drag.currentIndex) {
1257
+ drag.currentIndex = newIndex;
1258
+ selectedRange.value = {
1259
+ group: groupAttr,
1260
+ start: Math.min(drag.startIndex, newIndex),
1261
+ end: Math.max(drag.startIndex, newIndex)
1262
+ };
1263
+ }
1264
+ }
1265
+ break;
1266
+ }
1267
+ }
1268
+ };
1269
+ const handlePointerUp = () => {
1270
+ if (drag) {
1271
+ const { startIndex, currentIndex, group } = drag;
1272
+ if (startIndex !== currentIndex) input.onDragEnd?.()?.(Math.min(startIndex, currentIndex), Math.max(startIndex, currentIndex), group);
1273
+ }
1274
+ drag = null;
1275
+ selectedRange.value = null;
1276
+ };
1277
+ const removeListeners = () => {
1278
+ document.body.style.userSelect = savedUserSelect;
1279
+ document.removeEventListener("pointermove", handlePointerMove);
1280
+ document.removeEventListener("pointerup", handlePointerUp);
1281
+ };
1282
+ watch(() => selectedRange.value !== null, (isDragging) => {
1283
+ if (isDragging) {
1284
+ savedUserSelect = document.body.style.userSelect;
1285
+ document.body.style.userSelect = "none";
1286
+ document.addEventListener("pointermove", handlePointerMove);
1287
+ document.addEventListener("pointerup", handlePointerUp);
1288
+ } else removeListeners();
1289
+ });
1290
+ onBeforeUnmount(() => {
1291
+ if (selectedRange.value !== null) removeListeners();
1292
+ });
1293
+ const handleSlotPointerDown = (_event, index, group) => {
1294
+ if (!input.enabled()) return;
1295
+ drag = {
1296
+ group,
1297
+ startIndex: index,
1298
+ currentIndex: index
1299
+ };
1300
+ selectedRange.value = {
1301
+ group,
1302
+ start: index,
1303
+ end: index
1304
+ };
1305
+ };
1306
+ const isSlotSelected = (index, group) => {
1307
+ const range = selectedRange.value;
1308
+ if (!range || range.group !== group) return false;
1309
+ return index >= range.start && index <= range.end;
1310
+ };
1311
+ const isDragging = () => selectedRange.value !== null;
1312
+ return {
1313
+ handleSlotPointerDown,
1314
+ isSlotSelected,
1315
+ isDragging
1316
+ };
1317
+ }
1318
+ var ScheduleHeader_module_default = {
1319
+ header: "_header_1dfmx_1",
1320
+ navigationGroup: "_navigationGroup_1dfmx_11",
1321
+ todayControl: "_todayControl_1dfmx_25",
1322
+ viewSelect: "_viewSelect_1dfmx_31",
1323
+ compactViewSelect: "_compactViewSelect_1dfmx_37"
1324
+ };
1325
+ var HeaderControl_module_default = { headerControl: "_headerControl_6ykw9_1" };
1326
+ var ViewSelect_module_default = { viewSelect: "_viewSelect_1xfvc_1" };
1327
+ var MonthYearSelect_module_default = {
1328
+ monthYearSelectTarget: "_monthYearSelectTarget_2hd16_1",
1329
+ monthYearSelectList: "_monthYearSelectList_2hd16_10",
1330
+ monthYearSelectDropdown: "_monthYearSelectDropdown_2hd16_14",
1331
+ monthYearSelectLabel: "_monthYearSelectLabel_2hd16_24",
1332
+ monthYearSelectControl: "_monthYearSelectControl_2hd16_31"
1333
+ };
1334
+ //#endregion
1335
+ //#region src/components/ScheduleHeader/ScheduleHeader.ts
1336
+ var labelsKey = Symbol("schedule-header-labels");
1337
+ var commonControlProps = {
1338
+ active: Boolean,
1339
+ square: Boolean,
1340
+ radius: [String, Number],
1341
+ interactive: {
1342
+ type: Boolean,
1343
+ default: true
1344
+ },
1345
+ labels: Object
1346
+ };
1347
+ function resolveRadius(radius) {
1348
+ if (radius == null) return void 0;
1349
+ if (typeof radius === "number") return `${radius}px`;
1350
+ return [
1351
+ "xs",
1352
+ "sm",
1353
+ "md",
1354
+ "lg",
1355
+ "xl"
1356
+ ].includes(radius) ? `var(--mantine-radius-${radius})` : radius;
1357
+ }
1358
+ var HeaderControl = defineComponent({
1359
+ name: "HeaderControl",
1360
+ inheritAttrs: false,
1361
+ props: commonControlProps,
1362
+ setup(props, { attrs, slots }) {
1363
+ return () => h(UnstyledButton, {
1364
+ ...attrs,
1365
+ class: [HeaderControl_module_default.headerControl, attrs.class],
1366
+ style: [props.radius == null ? void 0 : { "--control-radius": resolveRadius(props.radius) }, attrs.style],
1367
+ tabindex: props.interactive ? attrs.tabindex : -1,
1368
+ mod: {
1369
+ active: props.active,
1370
+ square: props.square,
1371
+ interactive: props.interactive
1372
+ }
1373
+ }, () => slots.default?.());
1374
+ }
1375
+ });
1376
+ function directionalControl(name, type) {
1377
+ return defineComponent({
1378
+ name,
1379
+ inheritAttrs: false,
1380
+ props: commonControlProps,
1381
+ setup(props, { attrs }) {
1382
+ const inherited = inject(labelsKey, void 0);
1383
+ const { dir } = useDirection();
1384
+ return () => h(HeaderControl, {
1385
+ ...attrs,
1386
+ ...props,
1387
+ square: true,
1388
+ "data-type": type,
1389
+ "aria-label": getLabel(type, props.labels || inherited)
1390
+ }, () => h(AccordionChevron, { style: { transform: `rotate(${type === "next" ? dir.value === "rtl" ? 90 : -90 : dir.value === "rtl" ? -90 : 90}deg)` } }));
1391
+ }
1392
+ });
1393
+ }
1394
+ var ScheduleHeaderNext = directionalControl("ScheduleHeaderNext", "next");
1395
+ var ScheduleHeaderPrevious = directionalControl("ScheduleHeaderPrevious", "previous");
1396
+ var ScheduleHeaderToday = defineComponent({
1397
+ name: "ScheduleHeaderToday",
1398
+ inheritAttrs: false,
1399
+ props: commonControlProps,
1400
+ setup(props, { attrs }) {
1401
+ const inherited = inject(labelsKey, void 0);
1402
+ return () => h(HeaderControl, {
1403
+ ...attrs,
1404
+ ...props,
1405
+ "data-type": "today",
1406
+ "aria-label": getLabel("today", props.labels || inherited)
1407
+ }, () => getLabel("today", props.labels || inherited));
1408
+ }
1409
+ });
1410
+ var ViewSelect = defineComponent({
1411
+ name: "ViewSelect",
1412
+ inheritAttrs: false,
1413
+ props: {
1414
+ views: {
1415
+ type: Array,
1416
+ default: () => [
1417
+ "day",
1418
+ "week",
1419
+ "month",
1420
+ "year"
1421
+ ]
1422
+ },
1423
+ value: String,
1424
+ onChange: Function,
1425
+ radius: [String, Number],
1426
+ labels: Object
1427
+ },
1428
+ setup(props, { attrs }) {
1429
+ const inherited = inject(labelsKey, void 0);
1430
+ const switchLabels = {
1431
+ day: "switchToDayView",
1432
+ week: "switchToWeekView",
1433
+ month: "switchToMonthView",
1434
+ year: "switchToYearView"
1435
+ };
1436
+ const onKeydown = (event, index) => {
1437
+ const controls = event.currentTarget.parentElement?.querySelectorAll("[role=\"tab\"]");
1438
+ if (!controls?.length) return;
1439
+ let next = index;
1440
+ if (event.key === "ArrowRight") next = (index + 1) % controls.length;
1441
+ else if (event.key === "ArrowLeft") next = (index - 1 + controls.length) % controls.length;
1442
+ else if (event.key === "Home") next = 0;
1443
+ else if (event.key === "End") next = controls.length - 1;
1444
+ else return;
1445
+ event.preventDefault();
1446
+ controls[next]?.focus();
1447
+ };
1448
+ return () => {
1449
+ const labels = props.labels || inherited;
1450
+ return h(Box, {
1451
+ ...attrs,
1452
+ class: [ViewSelect_module_default.viewSelect, attrs.class],
1453
+ role: "tablist",
1454
+ "aria-label": getLabel("viewSelectLabel", labels)
1455
+ }, () => props.views.map((view, index) => h(HeaderControl, {
1456
+ active: view === props.value,
1457
+ radius: props.radius,
1458
+ role: "tab",
1459
+ "data-type": view,
1460
+ "aria-selected": view === props.value,
1461
+ "aria-label": getLabel(switchLabels[view], labels),
1462
+ tabindex: view === props.value ? 0 : -1,
1463
+ onClick: () => props.onChange?.(view),
1464
+ onKeydown: (event) => onKeydown(event, index)
1465
+ }, () => getLabel(view, labels))));
1466
+ };
1467
+ }
1468
+ });
1469
+ var MonthYearSelect = defineComponent({
1470
+ name: "MonthYearSelect",
1471
+ inheritAttrs: false,
1472
+ props: {
1473
+ locale: String,
1474
+ startYear: Number,
1475
+ endYear: Number,
1476
+ yearValue: Number,
1477
+ monthValue: Number,
1478
+ onYearChange: Function,
1479
+ onMonthChange: Function,
1480
+ monthsListFormat: [String, Function],
1481
+ labelFormat: [String, Function],
1482
+ radius: [String, Number],
1483
+ getYearControlProps: Function,
1484
+ getMonthControlProps: Function,
1485
+ withMonths: {
1486
+ type: Boolean,
1487
+ default: true
1488
+ },
1489
+ labels: Object
1490
+ },
1491
+ setup(props, { attrs }) {
1492
+ const inherited = inject(labelsKey, void 0);
1493
+ const opened = ref(false);
1494
+ const today = /* @__PURE__ */ new Date();
1495
+ return () => {
1496
+ const labels = props.labels || inherited;
1497
+ const startYear = props.startYear ?? today.getFullYear() - 5;
1498
+ const endYear = props.endYear ?? today.getFullYear() + 5;
1499
+ const selected = new Date(props.yearValue ?? today.getFullYear(), props.monthValue ?? today.getMonth(), 1);
1500
+ const hasActiveYear = props.yearValue !== void 0 && props.yearValue >= startYear && props.yearValue <= endYear;
1501
+ const months = props.withMonths ? getMonthsList({
1502
+ locale: props.locale || "en",
1503
+ format: props.monthsListFormat || "MMMM"
1504
+ }).map((month) => {
1505
+ const extra = props.getMonthControlProps?.(month.month) || {};
1506
+ return h(UnstyledButton, {
1507
+ ...extra,
1508
+ class: [MonthYearSelect_module_default.monthYearSelectControl, extra.class],
1509
+ mod: {
1510
+ type: "month",
1511
+ active: month.month === props.monthValue
1512
+ },
1513
+ tabindex: month.month === props.monthValue ? 0 : -1,
1514
+ "aria-label": `${getLabel("selectMonth", labels)} ${month.name}`,
1515
+ onKeydown: createScopedKeydownHandler({
1516
+ siblingSelector: "[data-type=\"month\"]:not(:disabled)",
1517
+ parentSelector: "[data-list]",
1518
+ activateOnFocus: false,
1519
+ loop: true,
1520
+ orientation: "vertical",
1521
+ onKeydown: extra.onKeydown
1522
+ }),
1523
+ onClick: () => {
1524
+ props.onMonthChange?.(month.month);
1525
+ }
1526
+ }, () => month.name);
1527
+ }) : [];
1528
+ const years = getYearsList({
1529
+ startYear,
1530
+ endYear
1531
+ }).map((year, index) => {
1532
+ const extra = props.getYearControlProps?.(year) || {};
1533
+ return h(UnstyledButton, {
1534
+ ...extra,
1535
+ class: [MonthYearSelect_module_default.monthYearSelectControl, extra.class],
1536
+ mod: {
1537
+ type: "year",
1538
+ active: year === props.yearValue
1539
+ },
1540
+ tabindex: hasActiveYear ? year === props.yearValue ? 0 : -1 : index === 0 ? 0 : -1,
1541
+ "aria-label": `${getLabel("selectYear", labels)} ${year}`,
1542
+ onKeydown: createScopedKeydownHandler({
1543
+ siblingSelector: "[data-type=\"year\"]:not(:disabled)",
1544
+ parentSelector: "[data-list]",
1545
+ activateOnFocus: false,
1546
+ loop: true,
1547
+ orientation: "vertical",
1548
+ onKeydown: extra.onKeydown
1549
+ }),
1550
+ onClick: () => {
1551
+ props.onYearChange?.(year);
1552
+ if (!props.withMonths) opened.value = false;
1553
+ }
1554
+ }, () => String(year));
1555
+ });
1556
+ return h(Popover, {
1557
+ position: "bottom-start",
1558
+ trapFocus: true,
1559
+ transitionProps: {
1560
+ transition: "pop",
1561
+ duration: 120
1562
+ },
1563
+ radius: props.radius || "var(--schedule-radius, var(--mantine-radius-default))",
1564
+ shadow: "md",
1565
+ offset: 3,
1566
+ width: props.withMonths ? void 0 : "target",
1567
+ opened: opened.value,
1568
+ onChange: (value) => {
1569
+ opened.value = value;
1570
+ }
1571
+ }, () => [h(Popover.Target, null, () => h(HeaderControl, {
1572
+ ...attrs,
1573
+ class: [MonthYearSelect_module_default.monthYearSelectTarget, attrs.class],
1574
+ radius: props.radius,
1575
+ "data-with-months": props.withMonths || void 0,
1576
+ onClick: () => {
1577
+ opened.value = !opened.value;
1578
+ }
1579
+ }, () => formatDate({
1580
+ date: selected,
1581
+ locale: props.locale || "en",
1582
+ format: props.labelFormat || (props.withMonths ? "MMMM YYYY" : "YYYY")
1583
+ }))), h(Popover.Dropdown, {
1584
+ class: MonthYearSelect_module_default.monthYearSelectDropdown,
1585
+ "data-with-months": props.withMonths || void 0
1586
+ }, () => [props.withMonths ? h(Box, {
1587
+ class: MonthYearSelect_module_default.monthYearSelectList,
1588
+ "data-list": true
1589
+ }, () => [h(Box, { class: MonthYearSelect_module_default.monthYearSelectLabel }, () => getLabel("month", labels)), ...months]) : null, h(Box, {
1590
+ class: MonthYearSelect_module_default.monthYearSelectList,
1591
+ "data-list": true
1592
+ }, () => [props.withMonths ? h(Box, { class: MonthYearSelect_module_default.monthYearSelectLabel }, () => getLabel("year", labels)) : null, ...years])])]);
1593
+ };
1594
+ }
1595
+ });
1596
+ var ScheduleHeaderBaseComponent = defineComponent({
1597
+ name: "ScheduleHeader",
1598
+ inheritAttrs: false,
1599
+ props: { labels: Object },
1600
+ setup(props, { attrs, slots }) {
1601
+ provide(labelsKey, props.labels);
1602
+ return () => h(Box, {
1603
+ ...attrs,
1604
+ class: [ScheduleHeader_module_default.header, attrs.class]
1605
+ }, () => slots.default?.());
1606
+ }
1607
+ });
1608
+ var ScheduleHeader = Object.assign(ScheduleHeaderBaseComponent, {
1609
+ Control: HeaderControl,
1610
+ Next: ScheduleHeaderNext,
1611
+ Previous: ScheduleHeaderPrevious,
1612
+ Today: ScheduleHeaderToday,
1613
+ ViewSelect,
1614
+ MonthYearSelect
1615
+ });
1616
+ //#endregion
1617
+ //#region src/components/ScheduleHeader/ScheduleHeaderBase.ts
1618
+ var ScheduleHeaderBase = defineComponent({
1619
+ name: "ScheduleHeaderBase",
1620
+ props: {
1621
+ view: {
1622
+ type: String,
1623
+ required: true
1624
+ },
1625
+ navigationHandlers: {
1626
+ type: Object,
1627
+ required: true
1628
+ },
1629
+ control: {
1630
+ type: Object,
1631
+ required: true
1632
+ },
1633
+ labels: Object,
1634
+ onDateChange: Function,
1635
+ onViewChange: Function,
1636
+ previousControlProps: Object,
1637
+ nextControlProps: Object,
1638
+ todayControlProps: Object,
1639
+ viewSelectProps: Object
1640
+ },
1641
+ setup(props) {
1642
+ return () => {
1643
+ const views = props.viewSelectProps?.views || [
1644
+ "day",
1645
+ "week",
1646
+ "month",
1647
+ "year"
1648
+ ];
1649
+ return h(ScheduleHeader, { labels: props.labels }, () => [
1650
+ h(Box, { class: ScheduleHeader_module_default.navigationGroup }, () => [
1651
+ h(ScheduleHeader.Previous, {
1652
+ ...props.previousControlProps,
1653
+ onClick: () => props.onDateChange?.(props.navigationHandlers.previous())
1654
+ }),
1655
+ props.control.monthYearSelect ? h(ScheduleHeader.MonthYearSelect, {
1656
+ ...props.control.monthYearSelect,
1657
+ labels: props.labels
1658
+ }) : h(ScheduleHeader.Control, { interactive: false }, () => props.control.title),
1659
+ h(ScheduleHeader.Next, {
1660
+ ...props.nextControlProps,
1661
+ onClick: () => props.onDateChange?.(props.navigationHandlers.next())
1662
+ })
1663
+ ]),
1664
+ h(Box, { class: ScheduleHeader_module_default.todayControl }, () => [h(ScheduleHeader.Today, {
1665
+ ...props.todayControlProps,
1666
+ onClick: () => props.onDateChange?.(props.navigationHandlers.today())
1667
+ })]),
1668
+ h(NativeSelect, {
1669
+ class: ScheduleHeader_module_default.compactViewSelect,
1670
+ value: props.view,
1671
+ size: "sm",
1672
+ data: views.map((view) => ({
1673
+ value: view,
1674
+ label: getLabel(view, props.labels)
1675
+ })),
1676
+ "aria-label": getLabel("viewSelectLabel", props.labels),
1677
+ onChange: (event) => props.onViewChange?.(event.currentTarget.value)
1678
+ }),
1679
+ h(Box, {
1680
+ class: ScheduleHeader_module_default.viewSelect,
1681
+ style: { marginInlineStart: "auto" }
1682
+ }, () => [h(ScheduleHeader.ViewSelect, {
1683
+ ...props.viewSelectProps,
1684
+ value: props.view,
1685
+ labels: props.labels,
1686
+ onChange: props.onViewChange
1687
+ })])
1688
+ ]);
1689
+ };
1690
+ }
1691
+ });
1692
+ function createHeaderNavigation(date, unit) {
1693
+ return {
1694
+ previous: () => toDateString(dayjs(date).subtract(1, unit)),
1695
+ next: () => toDateString(dayjs(date).add(1, unit)),
1696
+ today: () => toDateString(dayjs())
1697
+ };
1698
+ }
1699
+ //#endregion
1700
+ //#region src/components/DayView/get-day-view-events/get-day-positioned-events.ts
1701
+ function columnHasConflict$1({ columns, columnIndex, event, allDay, date }) {
1702
+ if (!columns[columnIndex]) return false;
1703
+ return columns[columnIndex].some((e) => {
1704
+ const eAllDay = isAllDayEvent({
1705
+ event: e,
1706
+ date
1707
+ });
1708
+ const hasTimeConflict = isEventsOverlap(e, event);
1709
+ if (allDay || eAllDay) return false;
1710
+ return hasTimeConflict;
1711
+ });
1712
+ }
1713
+ function getDayPositionedEvents({ events, startTime, endTime, intervalMinutes, date }) {
1714
+ const columns = [];
1715
+ const positioned = [];
1716
+ const sorted = sortEvents(events);
1717
+ for (const event of sorted) {
1718
+ const allDay = isAllDayEvent({
1719
+ event,
1720
+ date
1721
+ });
1722
+ let column = 0;
1723
+ while (columnHasConflict$1({
1724
+ columns,
1725
+ columnIndex: column,
1726
+ event,
1727
+ allDay,
1728
+ date
1729
+ })) column++;
1730
+ if (!columns[column]) columns[column] = [];
1731
+ columns[column].push(event);
1732
+ const verticalPosition = allDay ? {
1733
+ top: 0,
1734
+ height: 100
1735
+ } : getDayPosition({
1736
+ event,
1737
+ startTime,
1738
+ endTime,
1739
+ intervalMinutes
1740
+ });
1741
+ positioned.push({
1742
+ ...event,
1743
+ position: {
1744
+ ...verticalPosition,
1745
+ allDay,
1746
+ column,
1747
+ width: 0,
1748
+ offset: 0,
1749
+ overlaps: 0
1750
+ }
1751
+ });
1752
+ }
1753
+ for (const positionedEvent of positioned) {
1754
+ const { allDay, column } = positionedEvent.position;
1755
+ if (allDay) {
1756
+ positionedEvent.position.overlaps = 1;
1757
+ positionedEvent.position.width = 100;
1758
+ positionedEvent.position.offset = 0;
1759
+ continue;
1760
+ }
1761
+ const directlyOverlapping = [];
1762
+ for (const otherEvent of positioned) {
1763
+ if (otherEvent === positionedEvent || otherEvent.position.allDay) continue;
1764
+ if (isEventsOverlap(otherEvent, positionedEvent)) directlyOverlapping.push(otherEvent);
1765
+ }
1766
+ let maxColumn = column;
1767
+ for (const overlappingEvent of directlyOverlapping) {
1768
+ maxColumn = Math.max(maxColumn, overlappingEvent.position.column);
1769
+ for (const otherEvent of positioned) {
1770
+ if (otherEvent === overlappingEvent || otherEvent.position.allDay) continue;
1771
+ if (isEventsOverlap(otherEvent, overlappingEvent)) maxColumn = Math.max(maxColumn, otherEvent.position.column);
1772
+ }
1773
+ }
1774
+ const totalColumns = maxColumn + 1;
1775
+ let nextOccupiedColumn = totalColumns;
1776
+ for (const other of directlyOverlapping) if (other.position.column > column && other.position.column < nextOccupiedColumn) nextOccupiedColumn = other.position.column;
1777
+ const columnsSpanned = nextOccupiedColumn - column;
1778
+ positionedEvent.position.overlaps = totalColumns;
1779
+ positionedEvent.position.width = columnsSpanned / totalColumns * 100;
1780
+ positionedEvent.position.offset = column * 100 / totalColumns;
1781
+ }
1782
+ return positioned;
1783
+ }
1784
+ //#endregion
1785
+ //#region src/components/DayView/get-day-view-events/get-day-view-events.ts
1786
+ function getDayViewEvents({ events, date, startTime, endTime, intervalMinutes }) {
1787
+ if (events === void 0) return {
1788
+ allDayEvents: [],
1789
+ regularEvents: [],
1790
+ backgroundTimedEvents: [],
1791
+ backgroundAllDayEvents: []
1792
+ };
1793
+ const ids = /* @__PURE__ */ new Set();
1794
+ const filteredEvents = [];
1795
+ const backgroundFiltered = [];
1796
+ const dayStart = dayjs(date).startOf("day");
1797
+ const dayEnd = dayjs(date).endOf("day");
1798
+ for (const event of events) {
1799
+ const eventStart = dayjs(event.start);
1800
+ const eventEnd = dayjs(event.end);
1801
+ const isOnDay = eventStart.isSame(dayStart, "day");
1802
+ const spansIntoDay = !isOnDay && event.display === "background" && eventStart.isBefore(dayEnd) && eventEnd.isAfter(dayStart);
1803
+ if (isOnDay || spansIntoDay) {
1804
+ if (isOnDay && !isEventInTimeRange({
1805
+ event,
1806
+ startTime,
1807
+ endTime
1808
+ })) continue;
1809
+ const validated = validateEvent(event);
1810
+ if (!ids.has(event.id)) ids.add(event.id);
1811
+ else throw new Error(`[@mantine/schedule] DayView: Duplicated event ids found: ${event.id}`);
1812
+ if (event.display === "background") backgroundFiltered.push(validated);
1813
+ else filteredEvents.push(validated);
1814
+ }
1815
+ }
1816
+ const positionedEvents = getDayPositionedEvents({
1817
+ events: filteredEvents,
1818
+ startTime,
1819
+ endTime,
1820
+ intervalMinutes,
1821
+ date
1822
+ });
1823
+ const allDayEvents = [];
1824
+ const regularEvents = [];
1825
+ for (const event of positionedEvents) if (event.position.allDay) allDayEvents.push(event);
1826
+ else regularEvents.push(event);
1827
+ const backgroundTimedEvents = [];
1828
+ const backgroundAllDayEvents = [];
1829
+ for (const event of backgroundFiltered) {
1830
+ const eventStart = dayjs(event.start);
1831
+ const eventEnd = dayjs(event.end);
1832
+ const clippedStart = eventStart.isBefore(dayStart) ? dayStart : eventStart;
1833
+ const clippedEnd = eventEnd.isAfter(dayEnd) ? dayEnd : eventEnd;
1834
+ const clippedEvent = {
1835
+ ...event,
1836
+ start: clippedStart.format("YYYY-MM-DD HH:mm:ss"),
1837
+ end: clippedEnd.format("YYYY-MM-DD HH:mm:ss")
1838
+ };
1839
+ if (isAllDayEvent({
1840
+ event: clippedEvent,
1841
+ date
1842
+ })) backgroundAllDayEvents.push({
1843
+ ...event,
1844
+ position: {
1845
+ top: 0,
1846
+ height: 100,
1847
+ allDay: true,
1848
+ width: 100,
1849
+ offset: 0,
1850
+ column: 0,
1851
+ overlaps: 1
1852
+ }
1853
+ });
1854
+ else {
1855
+ const { top, height } = getDayPosition({
1856
+ event: clippedEvent,
1857
+ startTime,
1858
+ endTime,
1859
+ intervalMinutes
1860
+ });
1861
+ if (height <= 0) continue;
1862
+ backgroundTimedEvents.push({
1863
+ ...event,
1864
+ position: {
1865
+ top,
1866
+ height,
1867
+ allDay: false,
1868
+ width: 100,
1869
+ offset: 0,
1870
+ column: 0,
1871
+ overlaps: 1
1872
+ }
1873
+ });
1874
+ }
1875
+ }
1876
+ return {
1877
+ allDayEvents,
1878
+ regularEvents,
1879
+ backgroundTimedEvents,
1880
+ backgroundAllDayEvents
1881
+ };
1882
+ }
1883
+ var DayView_module_default = {
1884
+ dayView: "_dayView_wgb7d_1",
1885
+ dayViewHeader: "_dayViewHeader_wgb7d_22",
1886
+ dayViewScrollArea: "_dayViewScrollArea_wgb7d_32",
1887
+ dayViewInner: "_dayViewInner_wgb7d_42",
1888
+ dayViewTimeSlots: "_dayViewTimeSlots_wgb7d_46",
1889
+ dayViewSlot: "_dayViewSlot_wgb7d_49",
1890
+ dayViewSlotLabels: "_dayViewSlotLabels_wgb7d_54",
1891
+ dayViewSlotLabel: "_dayViewSlotLabel_wgb7d_54",
1892
+ dayViewSlots: "_dayViewSlots_wgb7d_84",
1893
+ dayViewBackgroundEvent: "_dayViewBackgroundEvent_wgb7d_188",
1894
+ dayViewAllDay: "_dayViewAllDay_wgb7d_201",
1895
+ dayViewAllDayEvents: "_dayViewAllDayEvents_wgb7d_206"
1896
+ };
1897
+ //#endregion
1898
+ //#region src/components/DayView/DayView.ts
1899
+ var DayView = defineComponent({
1900
+ name: "DayView",
1901
+ inheritAttrs: false,
1902
+ slots: Object,
1903
+ props: {
1904
+ ...timeViewProps,
1905
+ intervalMinutes: {
1906
+ type: Number,
1907
+ default: 15
1908
+ },
1909
+ headerFormat: {
1910
+ type: [String, Function],
1911
+ default: "MMMM D, YYYY"
1912
+ },
1913
+ withAllDaySlot: {
1914
+ type: Boolean,
1915
+ default: true
1916
+ },
1917
+ allDaySlotHeight: {
1918
+ type: [String, Number],
1919
+ default: 44
1920
+ },
1921
+ maxAllDayEvents: {
1922
+ type: Number,
1923
+ default: 3
1924
+ },
1925
+ moreEventsProps: Object
1926
+ },
1927
+ setup(props, { attrs, slots }) {
1928
+ const timeSlotsContainer = ref(null);
1929
+ const dropTargetSlotIndex = ref(null);
1930
+ const eventResize = useEventResize({
1931
+ enabled: () => props.withEventResize,
1932
+ mode: () => props.mode,
1933
+ startTime: () => props.startTime,
1934
+ endTime: () => props.endTime,
1935
+ intervalMinutes: () => props.intervalMinutes,
1936
+ onEventResize: () => props.onEventResize,
1937
+ canResizeEvent: () => props.canResizeEvent
1938
+ });
1939
+ const slotTimes = ref([]);
1940
+ const dayGroupRef = ref("");
1941
+ const slotDragSelect = useSlotDragSelect({
1942
+ enabled: () => props.withDragSlotSelect && props.mode !== "static",
1943
+ onDragEnd: () => props.onSlotDragEnd ? (startIndex, endIndex) => {
1944
+ const startSlot = slotTimes.value[startIndex];
1945
+ const endSlot = slotTimes.value[endIndex];
1946
+ if (startSlot && endSlot) props.onSlotDragEnd?.(`${dayGroupRef.value} ${startSlot.startTime}`, `${dayGroupRef.value} ${endSlot.endTime}`);
1947
+ } : void 0
1948
+ });
1949
+ return () => {
1950
+ const date = toDateString(props.date);
1951
+ const datePart = dayjs(date).format("YYYY-MM-DD");
1952
+ const now = dayjs(props.getCurrentTime?.() ?? dayjs());
1953
+ const showCurrentTimeIndicator = props.withCurrentTimeIndicator ?? dayjs(date).isSame(now, "day");
1954
+ const expanded = getExpandedEvents(props.events, dayjs(date).startOf("day").format("YYYY-MM-DD HH:mm:ss"), dayjs(date).endOf("day").format("YYYY-MM-DD HH:mm:ss"), props.recurrenceExpansionLimit);
1955
+ const { allDayEvents, regularEvents, backgroundTimedEvents, backgroundAllDayEvents } = getDayViewEvents({
1956
+ events: expanded,
1957
+ date,
1958
+ startTime: props.startTime,
1959
+ endTime: props.endTime,
1960
+ intervalMinutes: props.intervalMinutes
1961
+ });
1962
+ const intervals = getDayTimeIntervals({
1963
+ startTime: props.startTime,
1964
+ endTime: props.endTime,
1965
+ intervalMinutes: props.intervalMinutes
1966
+ });
1967
+ dayGroupRef.value = datePart;
1968
+ slotTimes.value = intervals.map((slot) => ({
1969
+ startTime: slot.startTime,
1970
+ endTime: slot.endTime
1971
+ }));
1972
+ const withSlotSelect = props.withDragSlotSelect && props.mode !== "static";
1973
+ const withDragHandlers = props.mode !== "static" && (props.withEventsDragAndDrop || Boolean(props.onExternalEventDrop));
1974
+ const { visibleEventsCount, hiddenEventsCount } = getVisibleEvents({
1975
+ maxEvents: props.maxAllDayEvents,
1976
+ totalEvents: allDayEvents.length
1977
+ });
1978
+ const emitDrop = (nativeEvent, target) => {
1979
+ nativeEvent.preventDefault();
1980
+ const event = getDropEvent(expanded, nativeEvent.dataTransfer);
1981
+ if (event) props.onEventDrop?.(moveEventTo(event, target));
1982
+ else if (nativeEvent.dataTransfer) props.onExternalEventDrop?.(nativeEvent.dataTransfer, target);
1983
+ };
1984
+ const emitAllDayDrop = (nativeEvent) => {
1985
+ nativeEvent.preventDefault();
1986
+ const event = getDropEvent(expanded, nativeEvent.dataTransfer);
1987
+ if (event) props.onEventDrop?.(moveEventToAllDay(event, datePart));
1988
+ else if (nativeEvent.dataTransfer) props.onExternalEventDrop?.(nativeEvent.dataTransfer, `${datePart} 00:00:00`);
1989
+ };
1990
+ const rootStyle = {
1991
+ "--day-view-radius": resolveScheduleRadius(props.radius),
1992
+ "--day-view-slot-height": typeof props.slotHeight === "number" ? `${props.slotHeight}px` : props.slotHeight,
1993
+ "--day-view-all-day-slot-height": typeof props.allDaySlotHeight === "number" ? `${props.allDaySlotHeight}px` : props.allDaySlotHeight
1994
+ };
1995
+ return h(Box, {
1996
+ ...attrs,
1997
+ class: [DayView_module_default.dayView, attrs.class],
1998
+ style: [rootStyle, attrs.style],
1999
+ mod: {
2000
+ static: props.mode === "static",
2001
+ "slot-dragging": slotDragSelect.isDragging()
2002
+ }
2003
+ }, () => [props.withHeader ? h(ScheduleHeaderBase, {
2004
+ view: "day",
2005
+ labels: props.labels,
2006
+ onDateChange: props.onDateChange,
2007
+ onViewChange: props.onViewChange,
2008
+ navigationHandlers: createHeaderNavigation(date, "day"),
2009
+ previousControlProps: props.previousControlProps,
2010
+ nextControlProps: props.nextControlProps,
2011
+ todayControlProps: props.todayControlProps,
2012
+ viewSelectProps: props.viewSelectProps,
2013
+ control: { title: formatDate({
2014
+ date,
2015
+ locale: props.locale || "en",
2016
+ format: props.headerFormat
2017
+ }) }
2018
+ }) : null, h(ScrollArea.Autosize, {
2019
+ class: DayView_module_default.dayViewScrollArea,
2020
+ scrollbarSize: 4
2021
+ }, () => [h(Box, { class: DayView_module_default.dayViewInner }, () => [h("div", { class: DayView_module_default.dayViewSlotLabels }, [props.withAllDaySlot ? h(Box, {
2022
+ class: DayView_module_default.dayViewSlotLabel,
2023
+ mod: { "all-day": true }
2024
+ }, () => getLabelSafe("allDay", props.labels)) : null, ...intervals.filter((slot) => slot.isHourStart).map((slot) => h(Box, { class: DayView_module_default.dayViewSlotLabel }, () => formatDate({
2025
+ date: `${datePart} ${slot.startTime}`,
2026
+ locale: props.locale || "en",
2027
+ format: props.slotLabelFormat
2028
+ })))]), h("div", { class: DayView_module_default.dayViewSlots }, [props.withAllDaySlot ? h("div", { class: DayView_module_default.dayViewAllDay }, [
2029
+ ...backgroundAllDayEvents.map((event) => h("div", {
2030
+ class: DayView_module_default.dayViewBackgroundEvent,
2031
+ key: event.id
2032
+ })),
2033
+ h("div", { class: DayView_module_default.dayViewAllDayEvents }, [...allDayEvents.slice(0, visibleEventsCount).map((event) => eventNode(event, props, {
2034
+ key: event.id,
2035
+ nowrap: true
2036
+ }, slots)), hiddenEventsCount > 0 ? h(MoreEvents, {
2037
+ events: allDayEvents,
2038
+ moreEventsCount: hiddenEventsCount,
2039
+ labels: props.labels,
2040
+ mode: props.mode,
2041
+ renderEvent: props.renderEvent,
2042
+ renderEventBody: props.renderEventBody,
2043
+ onEventClick: props.onEventClick,
2044
+ ...props.moreEventsProps
2045
+ }, forwardEventSlots(slots)) : null]),
2046
+ h(UnstyledButton, {
2047
+ class: DayView_module_default.dayViewSlot,
2048
+ mod: {
2049
+ "all-day": true,
2050
+ static: props.mode === "static"
2051
+ },
2052
+ tabindex: props.mode === "static" ? -1 : 0,
2053
+ "aria-label": `${getLabelSafe("timeSlot", props.labels)} ${getLabelSafe("allDay", props.labels)}`,
2054
+ onClick: props.mode === "static" ? void 0 : (event) => props.onAllDaySlotClick?.(date, event),
2055
+ onDragover: (event) => event.preventDefault(),
2056
+ onDrop: (event) => emitAllDayDrop(event)
2057
+ })
2058
+ ]) : null, h("div", {
2059
+ ref: timeSlotsContainer,
2060
+ class: DayView_module_default.dayViewTimeSlots,
2061
+ onDragover: withDragHandlers ? (event) => {
2062
+ event.preventDefault();
2063
+ if (!timeSlotsContainer.value) return;
2064
+ dropTargetSlotIndex.value = getTimeSlotDropTarget({
2065
+ nativeEvent: event,
2066
+ container: timeSlotsContainer.value,
2067
+ intervals,
2068
+ date: datePart
2069
+ })?.slotIndex ?? null;
2070
+ if (event.dataTransfer) event.dataTransfer.dropEffect = event.dataTransfer.types.includes("application/json") ? "move" : "copy";
2071
+ } : void 0,
2072
+ onDragleave: withDragHandlers ? (event) => {
2073
+ if (!(event.relatedTarget instanceof Node) || !timeSlotsContainer.value?.contains(event.relatedTarget)) dropTargetSlotIndex.value = null;
2074
+ } : void 0,
2075
+ onDrop: withDragHandlers ? (event) => {
2076
+ if (!timeSlotsContainer.value) return;
2077
+ const target = getTimeSlotDropTarget({
2078
+ nativeEvent: event,
2079
+ container: timeSlotsContainer.value,
2080
+ intervals,
2081
+ date: datePart
2082
+ });
2083
+ dropTargetSlotIndex.value = null;
2084
+ if (target) emitDrop(event, target.target);
2085
+ } : void 0
2086
+ }, [
2087
+ ...backgroundTimedEvents.map((event) => h("div", {
2088
+ key: event.id,
2089
+ class: DayView_module_default.dayViewBackgroundEvent,
2090
+ style: {
2091
+ top: `${event.position.top}%`,
2092
+ height: `${event.position.height}%`
2093
+ }
2094
+ })),
2095
+ ...regularEvents.map((event) => {
2096
+ const resizePosition = eventResize.getResizePosition(event.id);
2097
+ const isResizable = eventResize.isResizableEvent(event);
2098
+ return eventNode(event, props, {
2099
+ key: event.id,
2100
+ autoSize: true,
2101
+ style: {
2102
+ position: "absolute",
2103
+ top: `${resizePosition?.top ?? event.position.top}%`,
2104
+ height: `${resizePosition?.height ?? event.position.height}%`,
2105
+ width: `${event.position.width}%`,
2106
+ insetInlineStart: `${event.position.offset}%`
2107
+ },
2108
+ withResize: isResizable,
2109
+ isResizing: resizePosition !== null,
2110
+ onClick: props.onEventClick ? (nativeEvent) => {
2111
+ if (!eventResize.wasResizing()) props.onEventClick?.(event, nativeEvent);
2112
+ } : void 0,
2113
+ onResizeStart: (edge, pointerEvent) => {
2114
+ if (!timeSlotsContainer.value) return;
2115
+ eventResize.handleResizeStart({
2116
+ event,
2117
+ edge,
2118
+ container: timeSlotsContainer.value,
2119
+ originalTop: event.position.top,
2120
+ originalHeight: event.position.height,
2121
+ eventDate: datePart,
2122
+ pointerEvent
2123
+ });
2124
+ }
2125
+ }, slots);
2126
+ }),
2127
+ showCurrentTimeIndicator ? h(CurrentTimeIndicator, {
2128
+ startOffset: "calc(var(--day-view-slot-labels-width) * -1)",
2129
+ endOffset: "0rem",
2130
+ topOffset: "0rem",
2131
+ timeBubbleStartOffset: "calc(var(--day-view-slot-labels-width) * -1 + 30px)",
2132
+ currentTimeFormat: props.slotLabelFormat,
2133
+ startTime: props.startTime,
2134
+ endTime: props.endTime,
2135
+ intervalMinutes: props.intervalMinutes,
2136
+ withTimeBubble: props.withCurrentTimeBubble,
2137
+ withThumb: !props.withCurrentTimeBubble,
2138
+ getCurrentTime: props.getCurrentTime,
2139
+ locale: props.locale
2140
+ }) : null,
2141
+ ...intervals.map((slot, index) => {
2142
+ const start = dayjs(`${datePart} ${slot.startTime}`);
2143
+ const end = start.add(props.intervalMinutes, "minute");
2144
+ const mod = props.highlightBusinessHours ? getBusinessHoursMod({
2145
+ time: start.format("HH:mm:ss"),
2146
+ businessHours: props.businessHours || ["09:00:00", "17:00:00"],
2147
+ highlightBusinessHours: true,
2148
+ dayOfWeek: start.day()
2149
+ }) : {
2150
+ "business-hours": false,
2151
+ "non-business-hours": false
2152
+ };
2153
+ return h(UnstyledButton, {
2154
+ class: DayView_module_default.dayViewSlot,
2155
+ "data-time-slot-index": index,
2156
+ "data-drag-slot-index": withSlotSelect ? index : void 0,
2157
+ "data-drag-slot-group": withSlotSelect ? datePart : void 0,
2158
+ style: { "--slot-size": String(props.intervalMinutes / 60) },
2159
+ mod: {
2160
+ first: index === 0,
2161
+ "hour-start": slot.isHourStart,
2162
+ static: props.mode === "static",
2163
+ "drop-target": dropTargetSlotIndex.value === index,
2164
+ "drag-selected": slotDragSelect.isSlotSelected(index, datePart),
2165
+ "business-hours": mod["business-hours"],
2166
+ "non-business-hours": mod["non-business-hours"]
2167
+ },
2168
+ tabindex: props.mode === "static" ? -1 : index === 0 ? 0 : -1,
2169
+ onKeydown: props.mode === "static" ? void 0 : (event) => {
2170
+ const nextIndex = event.key === "ArrowDown" ? index + 1 : event.key === "ArrowUp" ? index - 1 : -1;
2171
+ if (nextIndex < 0 || nextIndex >= intervals.length) return;
2172
+ event.preventDefault();
2173
+ timeSlotsContainer.value?.querySelector(`[data-time-slot-index="${nextIndex}"]`)?.focus();
2174
+ },
2175
+ "aria-label": `${getLabelSafe("timeSlot", props.labels)} ${slot.startTime} - ${slot.endTime}`,
2176
+ onClick: (nativeEvent) => props.onTimeSlotClick?.({
2177
+ slotStart: start.format("YYYY-MM-DD HH:mm:ss"),
2178
+ slotEnd: end.format("YYYY-MM-DD HH:mm:ss"),
2179
+ nativeEvent
2180
+ }),
2181
+ onPointerdown: withSlotSelect ? (nativeEvent) => slotDragSelect.handleSlotPointerDown(nativeEvent, index, datePart) : void 0,
2182
+ onDragover: (event) => event.preventDefault()
2183
+ });
2184
+ })
2185
+ ])])])])]);
2186
+ };
2187
+ }
2188
+ });
2189
+ function getLabelSafe(key, labels) {
2190
+ return labels?.[key] || {
2191
+ allDay: "All day",
2192
+ timeSlot: "Time slot"
2193
+ }[key];
2194
+ }
2195
+ //#endregion
2196
+ //#region src/components/MobileMonthView/get-mobile-month-view-events.ts
2197
+ function groupEventByDate$1(event, groupedEvents) {
2198
+ if (isMultidayEvent(event)) {
2199
+ const startDate = dayjs(event.start).startOf("day");
2200
+ const endDate = dayjs(event.end).startOf("day");
2201
+ for (let date = startDate; date.isBefore(endDate) || date.isSame(endDate); date = date.add(1, "day")) {
2202
+ const dateKey = date.format("YYYY-MM-DD");
2203
+ if (!groupedEvents[dateKey]) groupedEvents[dateKey] = [];
2204
+ groupedEvents[dateKey].push(event);
2205
+ }
2206
+ return;
2207
+ }
2208
+ const eventDate = dayjs(event.start).format("YYYY-MM-DD");
2209
+ if (!groupedEvents[eventDate]) groupedEvents[eventDate] = [];
2210
+ groupedEvents[eventDate].push(event);
2211
+ }
2212
+ function getMobileMonthViewEvents({ date, events }) {
2213
+ const groupedEvents = {};
2214
+ if (events === void 0) return groupedEvents;
2215
+ const ids = /* @__PURE__ */ new Set();
2216
+ for (const event of events) {
2217
+ if (event.display === "background") continue;
2218
+ if (dayjs(event.start).isSame(dayjs(date), "month")) {
2219
+ groupEventByDate$1(validateEvent(event), groupedEvents);
2220
+ if (!ids.has(event.id)) ids.add(event.id);
2221
+ else throw new Error(`[@mantine/schedule] MobileMonthView: Duplicated event ids found: ${event.id}`);
2222
+ }
2223
+ }
2224
+ return groupedEvents;
2225
+ }
2226
+ var MobileMonthView_module_default = {
2227
+ mobileMonthView: "_mobileMonthView_vgzwg_1",
2228
+ mobileMonthViewHeader: "_mobileMonthViewHeader_vgzwg_24",
2229
+ mobileMonthViewHeaderBackButton: "_mobileMonthViewHeaderBackButton_vgzwg_32",
2230
+ mobileMonthViewHeaderLabel: "_mobileMonthViewHeaderLabel_vgzwg_47",
2231
+ mobileMonthViewCalendar: "_mobileMonthViewCalendar_vgzwg_53",
2232
+ mobileMonthViewWeekdays: "_mobileMonthViewWeekdays_vgzwg_61",
2233
+ mobileMonthViewWeekdaysCorner: "_mobileMonthViewWeekdaysCorner_vgzwg_66",
2234
+ mobileMonthViewWeekday: "_mobileMonthViewWeekday_vgzwg_61",
2235
+ mobileMonthViewWeek: "_mobileMonthViewWeek_vgzwg_61",
2236
+ mobileMonthViewWeekNumber: "_mobileMonthViewWeekNumber_vgzwg_89",
2237
+ mobileMonthViewDay: "_mobileMonthViewDay_vgzwg_119",
2238
+ mobileMonthViewDayIndicators: "_mobileMonthViewDayIndicators_vgzwg_208",
2239
+ mobileMonthViewDayIndicator: "_mobileMonthViewDayIndicator_vgzwg_208",
2240
+ mobileMonthViewEventsList: "_mobileMonthViewEventsList_vgzwg_224",
2241
+ mobileMonthViewEventsHeader: "_mobileMonthViewEventsHeader_vgzwg_232",
2242
+ mobileMonthViewEvent: "_mobileMonthViewEvent_vgzwg_224",
2243
+ mobileMonthViewEventBody: "_mobileMonthViewEventBody_vgzwg_259",
2244
+ mobileMonthViewEventColor: "_mobileMonthViewEventColor_vgzwg_265",
2245
+ mobileMonthViewEventTime: "_mobileMonthViewEventTime_vgzwg_271",
2246
+ mobileMonthViewNoEvents: "_mobileMonthViewNoEvents_vgzwg_277"
2247
+ };
2248
+ //#endregion
2249
+ //#region src/components/MobileMonthView/MobileMonthView.ts
2250
+ var MobileMonthView = defineComponent({
2251
+ name: "MobileMonthView",
2252
+ inheritAttrs: false,
2253
+ slots: Object,
2254
+ props: {
2255
+ ...baseViewProps,
2256
+ selectedDate: [
2257
+ String,
2258
+ Date,
2259
+ null
2260
+ ],
2261
+ defaultSelectedDate: [
2262
+ String,
2263
+ Date,
2264
+ null
2265
+ ],
2266
+ onSelectedDateChange: Function,
2267
+ withWeekNumbers: Boolean,
2268
+ withWeekDays: {
2269
+ type: Boolean,
2270
+ default: true
2271
+ },
2272
+ firstDayOfWeek: {
2273
+ type: Number,
2274
+ default: 1
2275
+ },
2276
+ weekdayFormat: {
2277
+ type: [String, Function],
2278
+ default: "dd"
2279
+ },
2280
+ weekendDays: {
2281
+ type: Array,
2282
+ default: () => [0, 6]
2283
+ },
2284
+ getWeekNumberProps: Function,
2285
+ getDayProps: Function,
2286
+ onDayClick: Function,
2287
+ onWeekNumberClick: Function,
2288
+ consistentWeeks: {
2289
+ type: Boolean,
2290
+ default: true
2291
+ },
2292
+ highlightToday: {
2293
+ type: Boolean,
2294
+ default: true
2295
+ },
2296
+ withOutsideDays: Boolean,
2297
+ eventsHeaderFormat: {
2298
+ type: [String, Function],
2299
+ default: "dddd, MMMM D"
2300
+ },
2301
+ onYearClick: Function,
2302
+ renderHeader: Function
2303
+ },
2304
+ setup(props, { attrs, slots }) {
2305
+ const { dir } = useDirection();
2306
+ const theme = useSafeMantineTheme();
2307
+ const internalSelected = ref(props.selectedDate !== void 0 ? props.selectedDate ? dayjs(props.selectedDate).format("YYYY-MM-DD") : null : dayjs(props.defaultSelectedDate ?? dayjs()).format("YYYY-MM-DD"));
2308
+ watch(() => props.selectedDate, (value) => {
2309
+ if (value !== void 0) internalSelected.value = value ? dayjs(value).format("YYYY-MM-DD") : null;
2310
+ }, { immediate: true });
2311
+ const select = (date) => {
2312
+ internalSelected.value = date;
2313
+ props.onSelectedDateChange?.(date);
2314
+ };
2315
+ return () => {
2316
+ const month = dayjs(props.date).startOf("month");
2317
+ const weeks = getMonthDays({
2318
+ month,
2319
+ firstDayOfWeek: props.firstDayOfWeek,
2320
+ consistentWeeks: props.consistentWeeks
2321
+ });
2322
+ const eventsByDay = getMobileMonthViewEvents({
2323
+ date: month,
2324
+ events: getExpandedEvents(props.events, weeks[0][0], dayjs(weeks.at(-1).at(-1)).endOf("day").format("YYYY-MM-DD HH:mm:ss"), props.recurrenceExpansionLimit)
2325
+ });
2326
+ const weekdays = getWeekdaysNames({
2327
+ locale: props.locale || "en",
2328
+ format: props.weekdayFormat,
2329
+ firstDayOfWeek: props.firstDayOfWeek
2330
+ });
2331
+ const selectedEvents = internalSelected.value ? eventsByDay[internalSelected.value] || [] : [];
2332
+ const headerDefault = [h(UnstyledButton, {
2333
+ class: MobileMonthView_module_default.mobileMonthViewHeaderBackButton,
2334
+ mod: { static: props.mode === "static" },
2335
+ tabindex: props.mode === "static" ? -1 : 0,
2336
+ onClick: props.mode === "static" ? void 0 : props.onYearClick
2337
+ }, () => [h(AccordionChevron, {
2338
+ size: 20,
2339
+ style: { transform: `rotate(${dir.value === "rtl" ? -90 : 90}deg)` }
2340
+ }), month.format("YYYY")]), h(Text, { class: MobileMonthView_module_default.mobileMonthViewHeaderLabel }, () => formatDate({
2341
+ date: month,
2342
+ locale: props.locale || "en",
2343
+ format: "MMMM YYYY"
2344
+ }))];
2345
+ return h(Box, {
2346
+ ...attrs,
2347
+ class: [MobileMonthView_module_default.mobileMonthView, attrs.class],
2348
+ style: [{ "--mobile-month-view-radius": resolveScheduleRadius(props.radius) }, attrs.style],
2349
+ mod: { "with-week-numbers": props.withWeekNumbers }
2350
+ }, () => [
2351
+ h("div", { class: MobileMonthView_module_default.mobileMonthViewHeader }, [props.renderHeader?.({
2352
+ mode: props.mode,
2353
+ date: props.date,
2354
+ defaultHeader: headerDefault
2355
+ }) || slots.header?.({
2356
+ mode: props.mode,
2357
+ date: props.date,
2358
+ defaultHeader: headerDefault
2359
+ }) || headerDefault]),
2360
+ h(Box, {
2361
+ class: MobileMonthView_module_default.mobileMonthViewCalendar,
2362
+ mod: { "with-weekdays": props.withWeekDays }
2363
+ }, () => [props.withWeekDays ? h("div", { class: MobileMonthView_module_default.mobileMonthViewWeekdays }, [props.withWeekNumbers ? h("span", { class: MobileMonthView_module_default.mobileMonthViewWeekdaysCorner }) : null, ...weekdays.map((weekday) => h("span", { class: MobileMonthView_module_default.mobileMonthViewWeekday }, [weekday]))]) : null, ...weeks.map((week) => h("div", { class: MobileMonthView_module_default.mobileMonthViewWeek }, [props.withWeekNumbers ? h(UnstyledButton, {
2364
+ class: MobileMonthView_module_default.mobileMonthViewWeekNumber,
2365
+ mod: { static: props.mode === "static" },
2366
+ tabindex: props.mode === "static" ? -1 : 0,
2367
+ ...props.getWeekNumberProps?.(dayjs(week[0]).format("YYYY-MM-DD")),
2368
+ onClick: (event) => props.onWeekNumberClick?.(dayjs(week[0]).format("YYYY-MM-DD"), event)
2369
+ }, () => String(getWeekNumber(week))) : null, ...week.map((date) => {
2370
+ const value = dayjs(date).format("YYYY-MM-DD");
2371
+ const outside = !dayjs(date).isSame(month, "month");
2372
+ const events = eventsByDay[value] || [];
2373
+ const extra = props.getDayProps?.(value) || {};
2374
+ const shouldRender = !outside || props.withOutsideDays;
2375
+ return h(UnstyledButton, {
2376
+ ...extra,
2377
+ class: [MobileMonthView_module_default.mobileMonthViewDay, extra.class],
2378
+ mod: {
2379
+ outside,
2380
+ weekend: props.weekendDays.includes(dayjs(date).day()),
2381
+ today: props.highlightToday && dayjs(date).isSame(dayjs(), "day"),
2382
+ selected: internalSelected.value === value,
2383
+ static: props.mode === "static",
2384
+ hidden: !shouldRender
2385
+ },
2386
+ tabindex: props.mode === "static" || !shouldRender ? -1 : 0,
2387
+ "aria-label": formatDate({
2388
+ date,
2389
+ locale: props.locale || "en",
2390
+ format: "MMMM D, YYYY"
2391
+ }),
2392
+ "aria-selected": internalSelected.value === value || void 0,
2393
+ onClick: props.mode === "static" || !shouldRender ? void 0 : (event) => {
2394
+ select(value);
2395
+ props.onDayClick?.(value, event);
2396
+ }
2397
+ }, () => [shouldRender ? String(dayjs(date).date()) : null, shouldRender && events.length ? h("span", { class: MobileMonthView_module_default.mobileMonthViewDayIndicators }, events.slice(0, 3).map((event) => h("span", {
2398
+ class: MobileMonthView_module_default.mobileMonthViewDayIndicator,
2399
+ style: { background: `var(--mantine-color-${event.color}-6, ${event.color})` }
2400
+ }))) : null]);
2401
+ })]))]),
2402
+ h(Box, { class: MobileMonthView_module_default.mobileMonthViewEventsList }, () => [h(Text, { class: MobileMonthView_module_default.mobileMonthViewEventsHeader }, () => internalSelected.value ? formatDate({
2403
+ date: internalSelected.value,
2404
+ locale: props.locale || "en",
2405
+ format: props.eventsHeaderFormat
2406
+ }) : ""), selectedEvents.length ? selectedEvents.map((event) => {
2407
+ const startTime = dayjs(event.start).format("HH:mm");
2408
+ const endTime = dayjs(event.end).format("HH:mm");
2409
+ const isAllDay = startTime === "00:00" && endTime === "00:00";
2410
+ const eventChildren = h(Box, { class: MobileMonthView_module_default.mobileMonthViewEventBody }, () => [h("div", {
2411
+ class: MobileMonthView_module_default.mobileMonthViewEventColor,
2412
+ style: { backgroundColor: getThemeColor(event.color, theme.value) }
2413
+ }), h("div", [h(Text, { class: MobileMonthView_module_default.mobileMonthViewEventTitle }, () => event.title), h(Text, { class: MobileMonthView_module_default.mobileMonthViewEventTime }, () => isAllDay ? "All day" : `${startTime} – ${endTime}`)])]);
2414
+ const rootProps = {
2415
+ type: "button",
2416
+ class: MobileMonthView_module_default.mobileMonthViewEvent,
2417
+ tabindex: props.mode === "static" ? -1 : 0,
2418
+ onClick: props.mode === "static" ? void 0 : (nativeEvent) => props.onEventClick?.(event, nativeEvent)
2419
+ };
2420
+ return props.renderEvent?.(event, {
2421
+ ...rootProps,
2422
+ children: eventChildren
2423
+ }) || slots.event?.({
2424
+ ...rootProps,
2425
+ children: eventChildren,
2426
+ event
2427
+ }) || h(UnstyledButton, {
2428
+ ...rootProps,
2429
+ key: event.id
2430
+ }, () => eventChildren);
2431
+ }) : h(Text, { class: MobileMonthView_module_default.mobileMonthViewNoEvents }, () => props.labels?.noEvents || "No events")])
2432
+ ]);
2433
+ };
2434
+ }
2435
+ });
2436
+ //#endregion
2437
+ //#region src/components/keyboard-navigation.ts
2438
+ function handleGridKeydown({ event, index, columns, total, getControl }) {
2439
+ const step = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : event.key === "ArrowDown" ? columns : event.key === "ArrowUp" ? -columns : 0;
2440
+ if (step === 0) return;
2441
+ event.preventDefault();
2442
+ for (let next = index + step; next >= 0 && next < total; next += step) {
2443
+ const control = getControl(next);
2444
+ if (control && !control.disabled && !control.hasAttribute("data-hidden")) {
2445
+ control.focus();
2446
+ return;
2447
+ }
2448
+ }
2449
+ }
2450
+ //#endregion
2451
+ //#region src/components/MonthView/get-month-view-events/add-event-to-day-groups.ts
2452
+ function addEventToDayGroups({ positionedEvent, eventStart, eventEnd, groupedByDay, eventsAddedToDay, weekIdx }) {
2453
+ if (weekIdx === 0 || !eventsAddedToDay.has(positionedEvent.id.toString())) {
2454
+ let dayDate = eventStart;
2455
+ while (dayDate.isBefore(eventEnd) || dayDate.isSame(eventEnd, "day")) {
2456
+ const dayDateStr = dayDate.format("YYYY-MM-DD 00:00:00");
2457
+ if (groupedByDay[dayDateStr]) groupedByDay[dayDateStr].push(positionedEvent);
2458
+ dayDate = dayDate.add(1, "day");
2459
+ }
2460
+ eventsAddedToDay.add(positionedEvent.id.toString());
2461
+ }
2462
+ }
2463
+ //#endregion
2464
+ //#region src/components/MonthView/get-month-view-events/calculate-event-position-in-week.ts
2465
+ function calculateEventPositionInWeek({ eventStart, eventEnd, weekStart, weekEnd, isMultiday }) {
2466
+ let displayStart = eventStart;
2467
+ let displayEnd = eventEnd;
2468
+ const hangingStart = eventStart.isBefore(weekStart);
2469
+ const hangingEnd = eventEnd.isAfter(weekEnd);
2470
+ const hanging = hangingStart && hangingEnd ? "both" : hangingStart ? "start" : hangingEnd ? "end" : "none";
2471
+ if (displayStart.isBefore(weekStart)) displayStart = weekStart;
2472
+ if (displayEnd.isAfter(weekEnd)) displayEnd = weekEnd;
2473
+ const startDayIndex = displayStart.diff(weekStart, "day");
2474
+ const endDayIndex = displayEnd.diff(weekStart, "day");
2475
+ const daysSpanned = Math.max(1, endDayIndex - startDayIndex + (isMultiday ? 1 : 0));
2476
+ return {
2477
+ startDayIndex,
2478
+ daysSpanned,
2479
+ startOffset: startDayIndex / 7 * 100,
2480
+ width: daysSpanned / 7 * 100,
2481
+ hanging
2482
+ };
2483
+ }
2484
+ //#endregion
2485
+ //#region src/components/MonthView/get-month-view-events/find-available-row.ts
2486
+ function findAvailableRow({ existingEvents, startDayIndex, daysSpanned, weekStart }) {
2487
+ let row = 0;
2488
+ for (const existing of existingEvents) {
2489
+ const existingStart = dayjs(existing.start).startOf("day");
2490
+ const existingDayIndex = (existingStart.isBefore(weekStart) || existingStart.isSame(weekStart, "day") ? weekStart : existingStart).diff(weekStart, "day");
2491
+ if (existingDayIndex + (existing.position?.width || 0) / 100 * 7 > startDayIndex && existingDayIndex < startDayIndex + daysSpanned) row = Math.max(row, (existing.position?.row || 0) + 1);
2492
+ }
2493
+ return row;
2494
+ }
2495
+ //#endregion
2496
+ //#region src/components/MonthView/get-month-view-events/get-weeks-in-range.ts
2497
+ function getWeeksInRange({ rangeStart, rangeEnd, firstDayOfWeek }) {
2498
+ const weeks = [];
2499
+ const groupedByDay = {};
2500
+ let currentDate = dayjs(getStartOfWeek({
2501
+ date: rangeStart.format("YYYY-MM-DD"),
2502
+ firstDayOfWeek
2503
+ }));
2504
+ while (currentDate.isBefore(rangeEnd) || currentDate.isSame(rangeEnd, "day")) {
2505
+ const week = [];
2506
+ for (let i = 0; i < 7; i++) {
2507
+ const dateStr = currentDate.format("YYYY-MM-DD 00:00:00");
2508
+ week.push(dateStr);
2509
+ if (!groupedByDay[dateStr]) groupedByDay[dateStr] = [];
2510
+ currentDate = currentDate.add(1, "day");
2511
+ }
2512
+ weeks.push(week);
2513
+ }
2514
+ return {
2515
+ weeks,
2516
+ groupedByDay
2517
+ };
2518
+ }
2519
+ //#endregion
2520
+ //#region src/components/MonthView/get-month-view-events/get-month-positioned-events.ts
2521
+ function getMonthPositionedEvents({ date, events, firstDayOfWeek = 1, range }) {
2522
+ const groupedByWeek = {};
2523
+ const backgroundByWeek = {};
2524
+ const eventsAddedToDay = /* @__PURE__ */ new Set();
2525
+ const { weeks, groupedByDay } = getWeeksInRange({
2526
+ rangeStart: range ? dayjs(range.start) : dayjs(date).startOf("month"),
2527
+ rangeEnd: range ? dayjs(range.end) : dayjs(date).startOf("month").endOf("month"),
2528
+ firstDayOfWeek
2529
+ });
2530
+ for (let i = 0; i < weeks.length; i++) {
2531
+ groupedByWeek[i.toString()] = [];
2532
+ backgroundByWeek[i.toString()] = [];
2533
+ }
2534
+ for (const event of events) {
2535
+ const eventStart = dayjs(event.start).startOf("day");
2536
+ const rawEnd = dayjs(event.end);
2537
+ const eventEnd = rawEnd.hour() === 0 && rawEnd.minute() === 0 && rawEnd.second() === 0 ? rawEnd.startOf("day").subtract(1, "day") : rawEnd.startOf("day");
2538
+ const isMultiday = eventEnd.isAfter(eventStart);
2539
+ for (let weekIdx = 0; weekIdx < weeks.length; weekIdx++) {
2540
+ const week = weeks[weekIdx];
2541
+ const weekStart = dayjs(week[0]).startOf("day");
2542
+ const weekEnd = dayjs(week[6]).endOf("day");
2543
+ if ((eventStart.isBefore(weekEnd) || eventStart.isSame(weekEnd, "day")) && (eventEnd.isAfter(weekStart) || eventEnd.isSame(weekStart, "day"))) {
2544
+ const { startDayIndex, daysSpanned, startOffset, width, hanging } = calculateEventPositionInWeek({
2545
+ eventStart,
2546
+ eventEnd,
2547
+ weekStart,
2548
+ weekEnd,
2549
+ isMultiday
2550
+ });
2551
+ if (event.display === "background") {
2552
+ backgroundByWeek[weekIdx.toString()].push({
2553
+ ...event,
2554
+ position: {
2555
+ startOffset,
2556
+ width,
2557
+ weekIndex: weekIdx,
2558
+ row: 0,
2559
+ hanging
2560
+ }
2561
+ });
2562
+ continue;
2563
+ }
2564
+ const row = findAvailableRow({
2565
+ existingEvents: groupedByWeek[weekIdx.toString()],
2566
+ startDayIndex,
2567
+ daysSpanned,
2568
+ weekStart
2569
+ });
2570
+ const positionedEvent = {
2571
+ ...event,
2572
+ position: {
2573
+ startOffset,
2574
+ width,
2575
+ weekIndex: weekIdx,
2576
+ row,
2577
+ hanging
2578
+ }
2579
+ };
2580
+ groupedByWeek[weekIdx.toString()].push(positionedEvent);
2581
+ addEventToDayGroups({
2582
+ positionedEvent,
2583
+ eventStart,
2584
+ eventEnd,
2585
+ groupedByDay,
2586
+ eventsAddedToDay,
2587
+ weekIdx
2588
+ });
2589
+ }
2590
+ }
2591
+ }
2592
+ return {
2593
+ groupedByWeek,
2594
+ groupedByDay,
2595
+ backgroundByWeek
2596
+ };
2597
+ }
2598
+ //#endregion
2599
+ //#region src/components/MonthView/get-month-view-events/get-month-view-events.ts
2600
+ function getMonthViewEvents({ date, events, firstDayOfWeek = 1, withOutsideDays, consistentWeeks }) {
2601
+ if (events === void 0) return {
2602
+ groupedByDay: {},
2603
+ groupedByWeek: {},
2604
+ backgroundByWeek: {}
2605
+ };
2606
+ const ids = /* @__PURE__ */ new Set();
2607
+ const filteredEvents = [];
2608
+ const range = getMonthRange({
2609
+ month: date,
2610
+ withOutsideDays,
2611
+ consistentWeeks,
2612
+ firstDayOfWeek
2613
+ });
2614
+ for (const event of events) if (dayjs(event.end).isAfter(range.start, "day") || dayjs(event.start).isBefore(range.end, "day")) {
2615
+ filteredEvents.push(validateEvent(event));
2616
+ if (!ids.has(event.id)) ids.add(event.id);
2617
+ else throw new Error(`[@mantine/schedule] MonthView: Duplicated event ids found: ${event.id}`);
2618
+ }
2619
+ return getMonthPositionedEvents({
2620
+ date,
2621
+ events: filteredEvents,
2622
+ firstDayOfWeek,
2623
+ range
2624
+ });
2625
+ }
2626
+ //#endregion
2627
+ //#region src/components/MonthView/get-renderable-month-event-segments.ts
2628
+ var DAYS_IN_WEEK = 7;
2629
+ var DAY_WIDTH = 100 / DAYS_IN_WEEK;
2630
+ function getEventDayRange(event) {
2631
+ const startDayIndex = Math.max(0, Math.round(event.position.startOffset / DAY_WIDTH));
2632
+ const daysSpanned = Math.max(1, Math.round(event.position.width / DAY_WIDTH));
2633
+ return {
2634
+ startDayIndex,
2635
+ endDayIndex: Math.min(DAYS_IN_WEEK - 1, startDayIndex + daysSpanned - 1)
2636
+ };
2637
+ }
2638
+ function getFirstAvailableRow(usedRows, maxEventsPerDay) {
2639
+ for (let row = 0; row < maxEventsPerDay; row += 1) if (!usedRows.has(row)) return row;
2640
+ return null;
2641
+ }
2642
+ function getSegmentHanging(originalHanging, touchesStart, touchesEnd) {
2643
+ const hangsFromStart = touchesStart && (originalHanging === "start" || originalHanging === "both");
2644
+ const hangsFromEnd = touchesEnd && (originalHanging === "end" || originalHanging === "both");
2645
+ if (hangsFromStart && hangsFromEnd) return "both";
2646
+ if (hangsFromStart) return "start";
2647
+ if (hangsFromEnd) return "end";
2648
+ return "none";
2649
+ }
2650
+ function getSegmentPosition(event, segment, eventRange) {
2651
+ const touchesStart = segment.startDayIndex === eventRange.startDayIndex;
2652
+ const touchesEnd = segment.endDayIndex === eventRange.endDayIndex;
2653
+ return {
2654
+ ...event.position,
2655
+ startOffset: segment.startDayIndex / DAYS_IN_WEEK * 100,
2656
+ width: (segment.endDayIndex - segment.startDayIndex + 1) / DAYS_IN_WEEK * 100,
2657
+ row: segment.row,
2658
+ hanging: getSegmentHanging(event.position.hanging, touchesStart, touchesEnd)
2659
+ };
2660
+ }
2661
+ function getEventKey(event) {
2662
+ return event.id;
2663
+ }
2664
+ function getRenderableMonthEventSegments({ events, groupedByDay, maxEventsPerDay, week }) {
2665
+ const eventIndexes = /* @__PURE__ */ new Map();
2666
+ const eventRanges = /* @__PURE__ */ new Map();
2667
+ const renderRows = /* @__PURE__ */ new Map();
2668
+ events.forEach((event, index) => {
2669
+ eventIndexes.set(event, index);
2670
+ eventRanges.set(event, getEventDayRange(event));
2671
+ });
2672
+ const setRenderRow = (event, dayIndex, row) => {
2673
+ if (!renderRows.has(event)) renderRows.set(event, /* @__PURE__ */ new Map());
2674
+ renderRows.get(event).set(dayIndex, row);
2675
+ };
2676
+ for (let dayIndex = 0; dayIndex < week.length; dayIndex += 1) {
2677
+ const dayEvents = groupedByDay[week[dayIndex]] || [];
2678
+ const dayEventIds = new Set(dayEvents.map((event) => getEventKey(event)));
2679
+ const dayWeekEvents = events.filter((event) => {
2680
+ const range = eventRanges.get(event);
2681
+ return dayEventIds.has(getEventKey(event)) && dayIndex >= range.startDayIndex && dayIndex <= range.endDayIndex;
2682
+ });
2683
+ if (dayEvents.length > maxEventsPerDay) {
2684
+ dayWeekEvents.forEach((event) => {
2685
+ if (event.position.row < maxEventsPerDay) setRenderRow(event, dayIndex, event.position.row);
2686
+ });
2687
+ continue;
2688
+ }
2689
+ const usedRows = /* @__PURE__ */ new Set();
2690
+ [...dayWeekEvents].sort((a, b) => {
2691
+ const rowDiff = a.position.row - b.position.row;
2692
+ if (rowDiff !== 0) return rowDiff;
2693
+ return eventIndexes.get(a) - eventIndexes.get(b);
2694
+ }).forEach((event) => {
2695
+ let row = event.position.row;
2696
+ if (row >= maxEventsPerDay || usedRows.has(row)) {
2697
+ const availableRow = getFirstAvailableRow(usedRows, maxEventsPerDay);
2698
+ if (availableRow === null) return;
2699
+ row = availableRow;
2700
+ }
2701
+ usedRows.add(row);
2702
+ setRenderRow(event, dayIndex, row);
2703
+ });
2704
+ }
2705
+ return events.flatMap((event) => {
2706
+ const eventRange = eventRanges.get(event);
2707
+ const eventRenderRows = renderRows.get(event);
2708
+ const segments = [];
2709
+ let currentSegment = null;
2710
+ const addSegment = (segment) => {
2711
+ const position = getSegmentPosition(event, segment, eventRange);
2712
+ segments.push({
2713
+ event,
2714
+ position,
2715
+ clipStart: segment.startDayIndex > eventRange.startDayIndex,
2716
+ clipEnd: segment.endDayIndex < eventRange.endDayIndex,
2717
+ key: `${event.id}-${event.position.weekIndex}-${segment.startDayIndex}-${segment.endDayIndex}-${segment.row}`
2718
+ });
2719
+ };
2720
+ for (let dayIndex = eventRange.startDayIndex; dayIndex <= eventRange.endDayIndex; dayIndex += 1) {
2721
+ const row = eventRenderRows?.get(dayIndex);
2722
+ if (row === void 0) {
2723
+ if (currentSegment) {
2724
+ addSegment(currentSegment);
2725
+ currentSegment = null;
2726
+ }
2727
+ continue;
2728
+ }
2729
+ if (currentSegment && currentSegment.row === row) currentSegment.endDayIndex = dayIndex;
2730
+ else {
2731
+ if (currentSegment) addSegment(currentSegment);
2732
+ currentSegment = {
2733
+ startDayIndex: dayIndex,
2734
+ endDayIndex: dayIndex,
2735
+ row
2736
+ };
2737
+ }
2738
+ }
2739
+ if (currentSegment) addSegment(currentSegment);
2740
+ return segments;
2741
+ });
2742
+ }
2743
+ var MonthView_module_default = {
2744
+ monthView: "_monthView_2aohq_1",
2745
+ monthViewWeekdays: "_monthViewWeekdays_2aohq_21",
2746
+ monthViewWeek: "_monthViewWeek_2aohq_21",
2747
+ monthViewWeekNumber: "_monthViewWeekNumber_2aohq_31",
2748
+ monthViewWeekday: "_monthViewWeekday_2aohq_21",
2749
+ monthViewWeekdaysCorner: "_monthViewWeekdaysCorner_2aohq_107",
2750
+ monthViewDay: "_monthViewDay_2aohq_114",
2751
+ monthViewDayLabel: "_monthViewDayLabel_2aohq_255",
2752
+ monthViewBackgroundEvent: "_monthViewBackgroundEvent_2aohq_271",
2753
+ monthViewEvents: "_monthViewEvents_2aohq_286"
2754
+ };
2755
+ //#endregion
2756
+ //#region src/components/MonthView/MonthView.ts
2757
+ var MonthView = defineComponent({
2758
+ name: "MonthView",
2759
+ inheritAttrs: false,
2760
+ slots: Object,
2761
+ props: {
2762
+ ...baseViewProps,
2763
+ firstDayOfWeek: {
2764
+ type: Number,
2765
+ default: 1
2766
+ },
2767
+ weekdayFormat: {
2768
+ type: [String, Function],
2769
+ default: "ddd"
2770
+ },
2771
+ weekendDays: {
2772
+ type: Array,
2773
+ default: () => [0, 6]
2774
+ },
2775
+ withWeekNumbers: Boolean,
2776
+ withWeekDays: {
2777
+ type: Boolean,
2778
+ default: true
2779
+ },
2780
+ consistentWeeks: {
2781
+ type: Boolean,
2782
+ default: true
2783
+ },
2784
+ highlightToday: {
2785
+ type: Boolean,
2786
+ default: true
2787
+ },
2788
+ withOutsideDays: {
2789
+ type: Boolean,
2790
+ default: true
2791
+ },
2792
+ maxEventsPerDay: {
2793
+ type: Number,
2794
+ default: 2
2795
+ },
2796
+ getDayProps: Function,
2797
+ getWeekNumberProps: Function,
2798
+ onDayClick: Function,
2799
+ onWeekNumberClick: Function,
2800
+ withEventsDragAndDrop: Boolean,
2801
+ onEventDrop: Function,
2802
+ canDragEvent: Function,
2803
+ onEventDragStart: Function,
2804
+ onEventDragEnd: Function,
2805
+ onExternalEventDrop: Function,
2806
+ withDragSlotSelect: Boolean,
2807
+ onSlotDragEnd: Function
2808
+ },
2809
+ setup(props, { attrs, slots }) {
2810
+ const monthGrid = ref(null);
2811
+ const dropTarget = ref(null);
2812
+ const monthGroup = "month";
2813
+ const flatDays = ref([]);
2814
+ const slotDragSelect = useSlotDragSelect({
2815
+ enabled: () => props.withDragSlotSelect && props.mode !== "static",
2816
+ onDragEnd: () => props.onSlotDragEnd ? (startIndex, endIndex) => {
2817
+ const startDay = flatDays.value[startIndex];
2818
+ const endDay = flatDays.value[endIndex];
2819
+ if (startDay && endDay) props.onSlotDragEnd?.(dayjs(startDay).startOf("day").format("YYYY-MM-DD HH:mm:ss"), dayjs(endDay).endOf("day").format("YYYY-MM-DD HH:mm:ss"));
2820
+ } : void 0
2821
+ });
2822
+ return () => {
2823
+ const month = dayjs(props.date).startOf("month");
2824
+ const maxEventsPerDay = Math.min(10, Math.max(1, props.maxEventsPerDay));
2825
+ const weeks = getMonthDays({
2826
+ month,
2827
+ firstDayOfWeek: props.firstDayOfWeek,
2828
+ consistentWeeks: props.consistentWeeks
2829
+ });
2830
+ flatDays.value = weeks.flat().map((date) => toDateString(date));
2831
+ const firstFocusableDayIndex = weeks.flat().findIndex((date) => props.withOutsideDays || dayjs(date).isSame(month, "month"));
2832
+ const withSlotSelect = props.withDragSlotSelect && props.mode !== "static";
2833
+ const rangeStart = weeks[0][0];
2834
+ const rangeEnd = weeks.at(-1).at(-1);
2835
+ const expanded = getExpandedEvents(props.events, rangeStart, dayjs(rangeEnd).endOf("day").format("YYYY-MM-DD HH:mm:ss"), props.recurrenceExpansionLimit);
2836
+ const grouped = getMonthViewEvents({
2837
+ date: month,
2838
+ events: expanded,
2839
+ firstDayOfWeek: props.firstDayOfWeek,
2840
+ withOutsideDays: props.withOutsideDays,
2841
+ consistentWeeks: props.consistentWeeks
2842
+ });
2843
+ const weekdays = getWeekdaysNames({
2844
+ locale: props.locale || "en",
2845
+ format: props.weekdayFormat,
2846
+ firstDayOfWeek: props.firstDayOfWeek
2847
+ });
2848
+ const withDragHandlers = props.mode !== "static" && (props.withEventsDragAndDrop || Boolean(props.onExternalEventDrop));
2849
+ const dragOver = (nativeEvent, date) => {
2850
+ nativeEvent.preventDefault();
2851
+ dropTarget.value = toDateString(date);
2852
+ if (nativeEvent.dataTransfer) nativeEvent.dataTransfer.dropEffect = nativeEvent.dataTransfer.types.includes("application/json") ? "move" : "copy";
2853
+ };
2854
+ const dragLeave = (nativeEvent) => {
2855
+ if (!(nativeEvent.relatedTarget instanceof Node) || !monthGrid.value?.contains(nativeEvent.relatedTarget)) dropTarget.value = null;
2856
+ };
2857
+ const drop = (nativeEvent, date) => {
2858
+ nativeEvent.preventDefault();
2859
+ dropTarget.value = null;
2860
+ const event = getDropEvent(expanded, nativeEvent.dataTransfer);
2861
+ if (event) {
2862
+ const { start } = calculateMonthDropDate({
2863
+ draggedEvent: event,
2864
+ targetDay: toDateString(date)
2865
+ });
2866
+ props.onEventDrop?.(moveEventTo(event, start));
2867
+ } else if (nativeEvent.dataTransfer) props.onExternalEventDrop?.(nativeEvent.dataTransfer, toDateString(date));
2868
+ };
2869
+ return h(Box, {
2870
+ ...attrs,
2871
+ class: [MonthView_module_default.monthView, attrs.class],
2872
+ style: [{
2873
+ "--month-view-radius": resolveScheduleRadius(props.radius),
2874
+ "--month-view-max-events": String(maxEventsPerDay)
2875
+ }, attrs.style],
2876
+ mod: {
2877
+ "with-week-numbers": props.withWeekNumbers,
2878
+ "with-weekdays": props.withWeekDays,
2879
+ static: props.mode === "static",
2880
+ "slot-dragging": slotDragSelect.isDragging()
2881
+ }
2882
+ }, () => [props.withHeader ? h(ScheduleHeaderBase, {
2883
+ view: "month",
2884
+ labels: props.labels,
2885
+ onDateChange: props.onDateChange,
2886
+ onViewChange: props.onViewChange,
2887
+ navigationHandlers: createHeaderNavigation(props.date, "month"),
2888
+ previousControlProps: props.previousControlProps,
2889
+ nextControlProps: props.nextControlProps,
2890
+ todayControlProps: props.todayControlProps,
2891
+ viewSelectProps: props.viewSelectProps,
2892
+ control: { monthYearSelect: {
2893
+ locale: props.locale,
2894
+ monthValue: month.month(),
2895
+ yearValue: month.year(),
2896
+ onMonthChange: (value) => props.onDateChange?.(toDateString(month.month(value))),
2897
+ onYearChange: (value) => props.onDateChange?.(toDateString(month.year(value)))
2898
+ } }
2899
+ }) : null, h(ScrollArea, {
2900
+ class: MonthView_module_default.monthViewScrollArea,
2901
+ scrollbarSize: 4
2902
+ }, () => h("div", {
2903
+ ref: monthGrid,
2904
+ class: MonthView_module_default.monthViewInner
2905
+ }, [props.withWeekDays ? h("div", { class: MonthView_module_default.monthViewWeekdays }, [props.withWeekNumbers ? h("div", { class: MonthView_module_default.monthViewWeekdaysCorner }) : null, ...weekdays.map((weekday) => h("div", { class: MonthView_module_default.monthViewWeekday }, [weekday]))]) : null, ...weeks.map((week, weekIndex) => {
2906
+ const segments = getRenderableMonthEventSegments({
2907
+ events: grouped.groupedByWeek[String(weekIndex)] || [],
2908
+ groupedByDay: grouped.groupedByDay,
2909
+ maxEventsPerDay,
2910
+ week
2911
+ });
2912
+ return h("div", { class: MonthView_module_default.monthViewWeek }, [
2913
+ props.withWeekNumbers ? h(UnstyledButton, {
2914
+ type: "button",
2915
+ class: MonthView_module_default.monthViewWeekNumber,
2916
+ ...props.getWeekNumberProps?.(toDateString(week[0])),
2917
+ onClick: (event) => props.onWeekNumberClick?.(toDateString(week[0]), event)
2918
+ }, () => String(getWeekNumber(week))) : null,
2919
+ ...week.map((date, dayIndex) => {
2920
+ const dateKey = dayjs(date).format("YYYY-MM-DD 00:00:00");
2921
+ const dayProps = props.getDayProps?.(toDateString(date)) || {};
2922
+ const events = grouped.groupedByDay[dateKey] || [];
2923
+ const hiddenCount = Math.max(0, events.length - maxEventsPerDay);
2924
+ const outside = !dayjs(date).isSame(month, "month");
2925
+ const gridIndex = weekIndex * 7 + dayIndex;
2926
+ return h("div", {
2927
+ class: MonthView_module_default.monthViewDay,
2928
+ "data-outside": outside || void 0,
2929
+ "data-weekend": props.weekendDays.includes(dayjs(date).day()) || void 0,
2930
+ "data-static": props.mode === "static" || void 0,
2931
+ "data-drop-target": dropTarget.value === toDateString(date) || void 0,
2932
+ "data-drag-selected": slotDragSelect.isSlotSelected(gridIndex, monthGroup) || void 0,
2933
+ "data-drag-slot-index": withSlotSelect ? gridIndex : void 0,
2934
+ "data-drag-slot-group": withSlotSelect ? monthGroup : void 0,
2935
+ onPointerdown: withSlotSelect ? (event) => slotDragSelect.handleSlotPointerDown(event, gridIndex, monthGroup) : void 0,
2936
+ onDragover: withDragHandlers ? (event) => dragOver(event, date) : (event) => event.preventDefault(),
2937
+ onDragleave: withDragHandlers ? dragLeave : void 0,
2938
+ onDrop: (event) => drop(event, date)
2939
+ }, [h(UnstyledButton, {
2940
+ type: "button",
2941
+ ...dayProps,
2942
+ class: [MonthView_module_default.monthViewDayLabel, dayProps.class],
2943
+ disabled: props.mode === "static",
2944
+ "data-grid-index": gridIndex,
2945
+ "data-outside": outside || void 0,
2946
+ "data-hidden": outside && !props.withOutsideDays || void 0,
2947
+ "aria-label": formatDate({
2948
+ date,
2949
+ locale: props.locale || "en",
2950
+ format: "MMMM D, YYYY"
2951
+ }),
2952
+ "data-today": props.highlightToday && dayjs(date).isSame(dayjs(), "day") || void 0,
2953
+ onClick: (event) => props.onDayClick?.(toDateString(date), event),
2954
+ tabindex: props.mode === "static" ? -1 : gridIndex === firstFocusableDayIndex ? 0 : -1,
2955
+ onKeydown: props.mode === "static" ? void 0 : (event) => {
2956
+ handleGridKeydown({
2957
+ event,
2958
+ index: gridIndex,
2959
+ columns: 7,
2960
+ total: weeks.length * 7,
2961
+ getControl: (index) => monthGrid.value?.querySelector(`[data-grid-index="${index}"]:not([data-hidden])`) ?? null
2962
+ });
2963
+ dayProps.onKeydown?.(event);
2964
+ }
2965
+ }, () => outside && !props.withOutsideDays ? "" : String(dayjs(date).date())), hiddenCount > 0 ? h(MoreEvents, {
2966
+ events,
2967
+ moreEventsCount: hiddenCount,
2968
+ labels: props.labels,
2969
+ renderEvent: props.renderEvent,
2970
+ renderEventBody: props.renderEventBody,
2971
+ onEventClick: props.onEventClick,
2972
+ mode: props.mode
2973
+ }, forwardEventSlots(slots)) : null]);
2974
+ }),
2975
+ h("div", { class: MonthView_module_default.monthViewEvents }, segments.map((segment) => eventNode(segment.event, props, {
2976
+ key: segment.key,
2977
+ nowrap: true,
2978
+ hanging: segment.position.hanging,
2979
+ "data-clip-start": segment.clipStart || void 0,
2980
+ "data-clip-end": segment.clipEnd || void 0,
2981
+ style: {
2982
+ position: "absolute",
2983
+ insetInlineStart: `${segment.position.startOffset}%`,
2984
+ width: `${segment.position.width}%`,
2985
+ top: `${28 + segment.position.row * 22}px`
2986
+ }
2987
+ }, slots)))
2988
+ ]);
2989
+ })]))]);
2990
+ };
2991
+ }
2992
+ });
2993
+ //#endregion
2994
+ //#region src/components/WeekView/get-week-label/get-week-label.ts
2995
+ function getWeekLabel({ weekdays, locale, weekLabelFormat, renderWeekLabel }) {
2996
+ if (renderWeekLabel) return renderWeekLabel({
2997
+ weekStart: dayjs(weekdays[0]).format("YYYY-MM-DD"),
2998
+ weekEnd: dayjs(weekdays[weekdays.length - 1]).format("YYYY-MM-DD")
2999
+ });
3000
+ return `${formatDate({
3001
+ locale,
3002
+ date: weekdays[0],
3003
+ format: weekLabelFormat
3004
+ })} – ${formatDate({
3005
+ locale,
3006
+ date: weekdays[weekdays.length - 1],
3007
+ format: weekLabelFormat
3008
+ })}, ${formatDate({
3009
+ locale,
3010
+ date: weekdays[0],
3011
+ format: "YYYY"
3012
+ })}`;
3013
+ }
3014
+ //#endregion
3015
+ //#region src/components/WeekView/get-week-view-events/filter-week-view-events.ts
3016
+ function filterWeekViewEvents({ date, events, startTime, endTime, firstDayOfWeek = 1 }) {
3017
+ if (events === void 0) return [];
3018
+ const ids = /* @__PURE__ */ new Set();
3019
+ const filteredEvents = [];
3020
+ for (const event of events) if (isWithinWeek({
3021
+ event,
3022
+ targetWeek: date,
3023
+ firstDayOfWeek
3024
+ }) && isEventInTimeRange({
3025
+ event,
3026
+ startTime,
3027
+ endTime
3028
+ })) {
3029
+ filteredEvents.push(validateEvent(event));
3030
+ if (!ids.has(event.id)) ids.add(event.id);
3031
+ else throw new Error(`[@mantine/schedule] WeekView: Duplicated event ids found: ${event.id}`);
3032
+ }
3033
+ return filteredEvents;
3034
+ }
3035
+ //#endregion
3036
+ //#region src/components/WeekView/get-week-view-events/assign-event-rows.ts
3037
+ function assignEventRows(events) {
3038
+ const eventRows = /* @__PURE__ */ new Map();
3039
+ for (const event of events) {
3040
+ let row = 0;
3041
+ while (true) {
3042
+ let hasConflict = false;
3043
+ for (const [otherEvent, otherRow] of eventRows.entries()) if (otherRow === row && isEventsOverlap(event, otherEvent)) {
3044
+ hasConflict = true;
3045
+ break;
3046
+ }
3047
+ if (!hasConflict) break;
3048
+ row++;
3049
+ }
3050
+ eventRows.set(event, row);
3051
+ }
3052
+ return eventRows;
3053
+ }
3054
+ //#endregion
3055
+ //#region src/components/WeekView/get-week-view-events/calculate-all-day-event-offset.ts
3056
+ function calculateAllDayEventOffset({ eventStartDate, weekStartDate, weekDays, visibleDaysCount, hangingStart }) {
3057
+ let displayStartDate = eventStartDate;
3058
+ if (hangingStart) displayStartDate = weekStartDate;
3059
+ if (!weekDays.some((day) => dayjs(day).isSame(displayStartDate, "day"))) displayStartDate = dayjs(weekDays[0]);
3060
+ return (weekDays.filter((day) => dayjs(day).isBefore(displayStartDate) || dayjs(day).isSame(displayStartDate, "day")).length - 1) / visibleDaysCount * 100;
3061
+ }
3062
+ //#endregion
3063
+ //#region src/components/WeekView/get-week-view-events/calculate-all-day-event-width.ts
3064
+ function calculateAllDayEventWidth({ eventStartDate, actualEndDate, weekStartDate, weekEndDate, weekDays, visibleDaysCount }) {
3065
+ let displayStartDate = eventStartDate;
3066
+ if (eventStartDate.isBefore(weekStartDate)) displayStartDate = weekStartDate;
3067
+ let displayEndDate = actualEndDate;
3068
+ if (actualEndDate.isAfter(weekEndDate)) displayEndDate = weekEndDate;
3069
+ return weekDays.filter((day) => (dayjs(day).isAfter(displayStartDate) || dayjs(day).isSame(displayStartDate, "day")) && (dayjs(day).isBefore(displayEndDate) || dayjs(day).isSame(displayEndDate, "day"))).length / visibleDaysCount * 100;
3070
+ }
3071
+ //#endregion
3072
+ //#region src/components/WeekView/get-week-view-events/calculate-event-days.ts
3073
+ function calculateEventDays({ event, weekDays, actualEndDate }) {
3074
+ const eventStartDate = dayjs(event.start).startOf("day");
3075
+ return weekDays.filter((day) => {
3076
+ const dayDate = dayjs(day).startOf("day");
3077
+ return (dayDate.isAfter(eventStartDate) || dayDate.isSame(eventStartDate)) && (dayDate.isBefore(actualEndDate) || dayDate.isSame(actualEndDate));
3078
+ });
3079
+ }
3080
+ //#endregion
3081
+ //#region src/components/WeekView/get-week-view-events/calculate-regular-event-overlaps.ts
3082
+ function calculateRegularEventOverlaps(events) {
3083
+ for (const event of events) {
3084
+ let maxOverlappingColumn = event.position.column;
3085
+ for (const otherEvent of events) if (isEventsOverlap(event, otherEvent)) maxOverlappingColumn = Math.max(maxOverlappingColumn, otherEvent.position.column);
3086
+ const overlaps = maxOverlappingColumn + 1;
3087
+ event.position.overlaps = overlaps;
3088
+ event.position.width = 100 / overlaps;
3089
+ event.position.offset = event.position.column * 100 / overlaps;
3090
+ }
3091
+ }
3092
+ //#endregion
3093
+ //#region src/components/WeekView/get-week-view-events/find-available-column.ts
3094
+ function columnHasConflict({ columns, columnIndex, event, allDay, allWeekDays }) {
3095
+ const columnKey = `col-${columnIndex}`;
3096
+ if (!columns.has(columnKey)) return false;
3097
+ return columns.get(columnKey).some((e) => {
3098
+ const eAllDay = allWeekDays.some((day) => isAllDayEvent({
3099
+ event: e,
3100
+ date: day
3101
+ }));
3102
+ const hasTimeConflict = isEventsOverlap(e, event);
3103
+ if (allDay && eAllDay) return hasTimeConflict;
3104
+ if (allDay || eAllDay) return false;
3105
+ return hasTimeConflict;
3106
+ });
3107
+ }
3108
+ function findAvailableColumn(input) {
3109
+ let column = 0;
3110
+ while (columnHasConflict({
3111
+ ...input,
3112
+ columnIndex: column
3113
+ })) column++;
3114
+ return column;
3115
+ }
3116
+ //#endregion
3117
+ //#region src/components/WeekView/get-week-view-events/get-event-end-date.ts
3118
+ function getEventEndDate(event) {
3119
+ const eventEndDate = dayjs(event.end).startOf("day");
3120
+ if (dayjs(event.end).hour() === 0 && dayjs(event.end).minute() === 0) return eventEndDate.subtract(1, "day");
3121
+ return eventEndDate;
3122
+ }
3123
+ //#endregion
3124
+ //#region src/components/WeekView/get-week-view-events/get-hanging-status.ts
3125
+ function getHangingStatus({ eventStartDate, actualEndDate, weekDays }) {
3126
+ const weekStartDate = dayjs(weekDays[0]);
3127
+ const weekEndDate = dayjs(weekDays[weekDays.length - 1]);
3128
+ const hangingStart = eventStartDate.isBefore(weekStartDate);
3129
+ const hangingEnd = actualEndDate.isAfter(weekEndDate);
3130
+ if (hangingStart && hangingEnd) return "both";
3131
+ if (hangingStart) return "start";
3132
+ if (hangingEnd) return "end";
3133
+ return "none";
3134
+ }
3135
+ //#endregion
3136
+ //#region src/components/WeekView/get-week-view-events/get-week-positioned-events.ts
3137
+ function getWeekPositionedEvents({ date, events, startTime, endTime, intervalMinutes, firstDayOfWeek = 1, weekendDays = [0, 6], withWeekendDays = true }) {
3138
+ const weekDays = getWeekDays({
3139
+ week: date,
3140
+ firstDayOfWeek,
3141
+ withWeekendDays,
3142
+ weekendDays
3143
+ });
3144
+ const visibleDaysCount = weekDays.length;
3145
+ const weekStartDate = dayjs(weekDays[0]);
3146
+ const weekEndDate = dayjs(weekDays[weekDays.length - 1]);
3147
+ const grouped = {
3148
+ allDayEvents: [],
3149
+ regularEvents: Object.fromEntries(weekDays.map((day) => [day, []])),
3150
+ backgroundEvents: Object.fromEntries(weekDays.map((day) => [day, []]))
3151
+ };
3152
+ const columns = /* @__PURE__ */ new Map();
3153
+ const allDayColumns = /* @__PURE__ */ new Map();
3154
+ const sorted = sortEvents(events);
3155
+ for (const event of sorted) {
3156
+ if (event.display === "background") {
3157
+ const eventStartDate = dayjs(event.start).startOf("day");
3158
+ const actualEndDate = getEventEndDate(event);
3159
+ const eventWeekDays = calculateEventDays({
3160
+ event,
3161
+ weekDays,
3162
+ actualEndDate
3163
+ });
3164
+ const hanging = getHangingStatus({
3165
+ eventStartDate,
3166
+ actualEndDate,
3167
+ weekDays
3168
+ });
3169
+ for (const day of eventWeekDays) {
3170
+ const visibleDayIndex = weekDays.indexOf(day);
3171
+ if (visibleDayIndex === -1) continue;
3172
+ const dayStart = dayjs(day);
3173
+ const dayEnd = dayStart.endOf("day");
3174
+ const eventStart = dayjs(event.start);
3175
+ const eventEnd = dayjs(event.end);
3176
+ const clippedStart = eventStart.isBefore(dayStart) ? dayStart : eventStart;
3177
+ const clippedEnd = eventEnd.isAfter(dayEnd) ? dayEnd : eventEnd;
3178
+ const clippedEvent = {
3179
+ ...event,
3180
+ start: clippedStart.format("YYYY-MM-DD HH:mm:ss"),
3181
+ end: clippedEnd.format("YYYY-MM-DD HH:mm:ss")
3182
+ };
3183
+ const isAllDay = isAllDayEvent({
3184
+ event: clippedEvent,
3185
+ date: day
3186
+ });
3187
+ const verticalPosition = isAllDay ? {
3188
+ top: 0,
3189
+ height: 100
3190
+ } : getDayPosition({
3191
+ event: clippedEvent,
3192
+ startTime,
3193
+ endTime,
3194
+ intervalMinutes
3195
+ });
3196
+ if (!isAllDay && verticalPosition.height <= 0) continue;
3197
+ const dayWeekOffset = visibleDayIndex / visibleDaysCount * 100;
3198
+ grouped.backgroundEvents[day].push({
3199
+ ...event,
3200
+ position: {
3201
+ ...verticalPosition,
3202
+ allDay: isAllDay,
3203
+ column: 0,
3204
+ width: 100,
3205
+ offset: 0,
3206
+ overlaps: 1,
3207
+ weekOffset: dayWeekOffset,
3208
+ row: 0,
3209
+ hanging
3210
+ }
3211
+ });
3212
+ }
3213
+ continue;
3214
+ }
3215
+ const eventStartDate = dayjs(event.start).startOf("day");
3216
+ const actualEndDate = getEventEndDate(event);
3217
+ const eventWeekDays = calculateEventDays({
3218
+ event,
3219
+ weekDays,
3220
+ actualEndDate
3221
+ });
3222
+ if (eventWeekDays.length === 0) continue;
3223
+ const isMultiday = actualEndDate.isAfter(eventStartDate);
3224
+ const hanging = getHangingStatus({
3225
+ eventStartDate,
3226
+ actualEndDate,
3227
+ weekDays
3228
+ });
3229
+ const isActuallyAllDay = eventWeekDays.some((day) => isAllDayEvent({
3230
+ event,
3231
+ date: day
3232
+ }));
3233
+ const allDay = isMultiday || isActuallyAllDay;
3234
+ const columnMap = allDay ? allDayColumns : columns;
3235
+ const column = findAvailableColumn({
3236
+ columns: columnMap,
3237
+ event,
3238
+ allDay,
3239
+ allWeekDays: weekDays
3240
+ });
3241
+ const columnKey = `col-${column}`;
3242
+ if (!columnMap.has(columnKey)) columnMap.set(columnKey, []);
3243
+ columnMap.get(columnKey).push(event);
3244
+ const verticalPosition = allDay ? {
3245
+ top: 0,
3246
+ height: 100
3247
+ } : getDayPosition({
3248
+ event,
3249
+ startTime,
3250
+ endTime,
3251
+ intervalMinutes
3252
+ });
3253
+ if (allDay) {
3254
+ const offset = calculateAllDayEventOffset({
3255
+ eventStartDate,
3256
+ weekStartDate,
3257
+ weekDays,
3258
+ visibleDaysCount,
3259
+ hangingStart: hanging === "start" || hanging === "both"
3260
+ });
3261
+ grouped.allDayEvents.push({
3262
+ ...event,
3263
+ position: {
3264
+ ...verticalPosition,
3265
+ allDay,
3266
+ column,
3267
+ width: 0,
3268
+ offset,
3269
+ overlaps: 0,
3270
+ row: 0,
3271
+ hanging
3272
+ }
3273
+ });
3274
+ } else for (const day of eventWeekDays) {
3275
+ const visibleDayIndex = weekDays.indexOf(day);
3276
+ if (visibleDayIndex === -1) continue;
3277
+ const dayWeekOffset = visibleDayIndex / visibleDaysCount * 100;
3278
+ grouped.regularEvents[day].push({
3279
+ ...event,
3280
+ position: {
3281
+ ...verticalPosition,
3282
+ allDay,
3283
+ column,
3284
+ width: 0,
3285
+ offset: 0,
3286
+ overlaps: 0,
3287
+ weekOffset: dayWeekOffset,
3288
+ row: 0,
3289
+ hanging
3290
+ }
3291
+ });
3292
+ }
3293
+ }
3294
+ for (const day of weekDays) calculateRegularEventOverlaps(grouped.regularEvents[day]);
3295
+ if (grouped.allDayEvents.length > 0) {
3296
+ const eventRows = assignEventRows(grouped.allDayEvents);
3297
+ const assignedRows = /* @__PURE__ */ new Set();
3298
+ for (const event of grouped.allDayEvents) {
3299
+ const row = eventRows.get(event);
3300
+ event.position.row = row;
3301
+ assignedRows.add(row);
3302
+ }
3303
+ const rowCount = Math.max(...assignedRows) + 1;
3304
+ for (const event of grouped.allDayEvents) {
3305
+ const eventStartDate = dayjs(event.start).startOf("day");
3306
+ const actualEndDate = getEventEndDate(event);
3307
+ event.position.width = calculateAllDayEventWidth({
3308
+ eventStartDate,
3309
+ actualEndDate,
3310
+ weekStartDate,
3311
+ weekEndDate,
3312
+ weekDays,
3313
+ visibleDaysCount
3314
+ });
3315
+ event.position.overlaps = rowCount;
3316
+ }
3317
+ }
3318
+ return grouped;
3319
+ }
3320
+ //#endregion
3321
+ //#region src/components/WeekView/get-week-view-events/get-week-view-events.ts
3322
+ function getWeekViewEvents(input) {
3323
+ return getWeekPositionedEvents({
3324
+ ...input,
3325
+ events: filterWeekViewEvents(input)
3326
+ });
3327
+ }
3328
+ var WeekView_module_default = {
3329
+ weekView: "_weekView_16qgh_1",
3330
+ weekViewRoot: "_weekViewRoot_16qgh_22",
3331
+ weekViewInner: "_weekViewInner_16qgh_30",
3332
+ weekViewScrollArea: "_weekViewScrollArea_16qgh_36",
3333
+ weekViewHeader: "_weekViewHeader_16qgh_42",
3334
+ weekViewCorner: "_weekViewCorner_16qgh_57",
3335
+ weekViewSlotLabels: "_weekViewSlotLabels_16qgh_68",
3336
+ weekViewSlotLabel: "_weekViewSlotLabel_16qgh_68",
3337
+ weekViewDay: "_weekViewDay_16qgh_95",
3338
+ weekViewDayLabel: "_weekViewDayLabel_16qgh_100",
3339
+ weekViewDayNumber: "_weekViewDayNumber_16qgh_138",
3340
+ weekViewDayWeekday: "_weekViewDayWeekday_16qgh_154",
3341
+ weekViewBackgroundEvent: "_weekViewBackgroundEvent_16qgh_160",
3342
+ weekViewDaySlots: "_weekViewDaySlots_16qgh_173",
3343
+ weekViewDaySlot: "_weekViewDaySlot_16qgh_173",
3344
+ weekViewWeekLabel: "_weekViewWeekLabel_16qgh_271",
3345
+ weekViewWeekNumber: "_weekViewWeekNumber_16qgh_277",
3346
+ weekViewAllDaySlots: "_weekViewAllDaySlots_16qgh_283",
3347
+ weekViewAllDaySlotsLabel: "_weekViewAllDaySlotsLabel_16qgh_288",
3348
+ weekViewAllDaySlotsEvents: "_weekViewAllDaySlotsEvents_16qgh_295",
3349
+ weekViewAllDaySlotsList: "_weekViewAllDaySlotsList_16qgh_302"
3350
+ };
3351
+ //#endregion
3352
+ //#region src/components/WeekView/WeekView.ts
3353
+ var WeekView = defineComponent({
3354
+ name: "WeekView",
3355
+ inheritAttrs: false,
3356
+ slots: Object,
3357
+ props: {
3358
+ ...timeViewProps,
3359
+ withCurrentTimeIndicator: {
3360
+ type: Boolean,
3361
+ default: true
3362
+ },
3363
+ forceCurrentTimeIndicator: Boolean,
3364
+ firstDayOfWeek: {
3365
+ type: Number,
3366
+ default: 1
3367
+ },
3368
+ weekdayFormat: {
3369
+ type: [String, Function],
3370
+ default: "ddd"
3371
+ },
3372
+ dayFormat: {
3373
+ type: [String, Function],
3374
+ default: "D"
3375
+ },
3376
+ withWeekNumber: {
3377
+ type: Boolean,
3378
+ default: true
3379
+ },
3380
+ withAllDaySlots: {
3381
+ type: Boolean,
3382
+ default: true
3383
+ },
3384
+ withWeekNumbers: {
3385
+ type: Boolean,
3386
+ default: void 0
3387
+ },
3388
+ withAllDaySlot: {
3389
+ type: Boolean,
3390
+ default: void 0
3391
+ },
3392
+ allDaySlotsHeight: {
3393
+ type: [String, Number],
3394
+ default: 44
3395
+ },
3396
+ maxAllDayEvents: {
3397
+ type: Number,
3398
+ default: 3
3399
+ },
3400
+ weekendDays: {
3401
+ type: Array,
3402
+ default: () => [0, 6]
3403
+ },
3404
+ withWeekendDays: {
3405
+ type: Boolean,
3406
+ default: true
3407
+ },
3408
+ weekLabelFormat: {
3409
+ type: [String, Function],
3410
+ default: "MMM D"
3411
+ },
3412
+ renderWeekLabel: Function
3413
+ },
3414
+ setup(props, { attrs, slots }) {
3415
+ const daySlotsContainers = /* @__PURE__ */ new Map();
3416
+ const dropTarget = ref(null);
3417
+ const eventResize = useEventResize({
3418
+ enabled: () => props.withEventResize,
3419
+ mode: () => props.mode,
3420
+ startTime: () => props.startTime,
3421
+ endTime: () => props.endTime,
3422
+ intervalMinutes: () => props.intervalMinutes,
3423
+ onEventResize: () => props.onEventResize,
3424
+ canResizeEvent: () => props.canResizeEvent
3425
+ });
3426
+ const slotTimes = ref([]);
3427
+ const slotDragSelect = useSlotDragSelect({
3428
+ enabled: () => props.withDragSlotSelect && props.mode !== "static",
3429
+ onDragEnd: () => props.onSlotDragEnd ? (startIndex, endIndex, group) => {
3430
+ const slotDate = dayjs(group).format("YYYY-MM-DD");
3431
+ const startSlot = slotTimes.value[startIndex];
3432
+ const endSlot = slotTimes.value[endIndex];
3433
+ if (startSlot && endSlot) props.onSlotDragEnd?.(`${slotDate} ${startSlot.startTime}`, `${slotDate} ${endSlot.endTime}`);
3434
+ } : void 0
3435
+ });
3436
+ return () => {
3437
+ const withWeekNumber = props.withWeekNumbers ?? props.withWeekNumber;
3438
+ const withAllDaySlots = props.withAllDaySlot ?? props.withAllDaySlots;
3439
+ const days = getWeekDays({
3440
+ week: props.date,
3441
+ firstDayOfWeek: props.firstDayOfWeek,
3442
+ withWeekendDays: props.withWeekendDays,
3443
+ weekendDays: props.weekendDays
3444
+ });
3445
+ const now = dayjs(props.getCurrentTime?.() ?? dayjs());
3446
+ const currentWeekdayIndex = props.withCurrentTimeIndicator ? props.forceCurrentTimeIndicator ? days.findIndex((date) => dayjs(date).day() === now.day()) : days.findIndex((date) => dayjs(date).isSame(now, "day")) : -1;
3447
+ const expanded = getExpandedEvents(props.events, dayjs(days[0]).startOf("day").format("YYYY-MM-DD HH:mm:ss"), dayjs(days.at(-1)).endOf("day").format("YYYY-MM-DD HH:mm:ss"), props.recurrenceExpansionLimit);
3448
+ const grouped = getWeekViewEvents({
3449
+ date: props.date,
3450
+ events: expanded,
3451
+ startTime: props.startTime,
3452
+ endTime: props.endTime,
3453
+ intervalMinutes: props.intervalMinutes,
3454
+ firstDayOfWeek: props.firstDayOfWeek,
3455
+ weekendDays: props.weekendDays,
3456
+ withWeekendDays: props.withWeekendDays
3457
+ });
3458
+ const intervals = getDayTimeIntervals({
3459
+ startTime: props.startTime,
3460
+ endTime: props.endTime,
3461
+ intervalMinutes: props.intervalMinutes
3462
+ });
3463
+ slotTimes.value = intervals.map((slot) => ({
3464
+ startTime: slot.startTime,
3465
+ endTime: slot.endTime
3466
+ }));
3467
+ const withSlotSelect = props.withDragSlotSelect && props.mode !== "static";
3468
+ const getWeekRoot = (event) => event.currentTarget.closest(`.${WeekView_module_default.weekViewRoot}`);
3469
+ const focusWeekControl = (event, selector) => {
3470
+ const control = getWeekRoot(event)?.querySelector(selector);
3471
+ if (!control || control.disabled) return;
3472
+ event.preventDefault();
3473
+ control.focus();
3474
+ };
3475
+ const withDragHandlers = props.mode !== "static" && (props.withEventsDragAndDrop || Boolean(props.onExternalEventDrop));
3476
+ const emitDrop = (nativeEvent, target) => {
3477
+ nativeEvent.preventDefault();
3478
+ const event = getDropEvent(expanded, nativeEvent.dataTransfer);
3479
+ if (event) props.onEventDrop?.(moveEventTo(event, target));
3480
+ else if (nativeEvent.dataTransfer) props.onExternalEventDrop?.(nativeEvent.dataTransfer, target);
3481
+ };
3482
+ const emitAllDayDrop = (nativeEvent, date) => {
3483
+ nativeEvent.preventDefault();
3484
+ const dayKey = dayjs(date).format("YYYY-MM-DD");
3485
+ const event = getDropEvent(expanded, nativeEvent.dataTransfer);
3486
+ if (event) props.onEventDrop?.(moveEventToAllDay(event, dayKey));
3487
+ else if (nativeEvent.dataTransfer) props.onExternalEventDrop?.(nativeEvent.dataTransfer, `${dayKey} 00:00:00`);
3488
+ };
3489
+ const rootStyle = {
3490
+ "--week-view-radius": resolveScheduleRadius(props.radius),
3491
+ "--week-view-slot-height": typeof props.slotHeight === "number" ? `${props.slotHeight}px` : props.slotHeight,
3492
+ "--week-view-all-day-slots-height": typeof props.allDaySlotsHeight === "number" ? `${props.allDaySlotsHeight}px` : props.allDaySlotsHeight
3493
+ };
3494
+ return h(Box, {
3495
+ ...attrs,
3496
+ class: [WeekView_module_default.weekView, attrs.class],
3497
+ style: [rootStyle, attrs.style],
3498
+ mod: {
3499
+ static: props.mode === "static",
3500
+ "slot-dragging": slotDragSelect.isDragging()
3501
+ }
3502
+ }, () => [props.withHeader ? h(ScheduleHeaderBase, {
3503
+ view: "week",
3504
+ labels: props.labels,
3505
+ onDateChange: props.onDateChange,
3506
+ onViewChange: props.onViewChange,
3507
+ navigationHandlers: createHeaderNavigation(props.date, "week"),
3508
+ previousControlProps: props.previousControlProps,
3509
+ nextControlProps: props.nextControlProps,
3510
+ todayControlProps: props.todayControlProps,
3511
+ viewSelectProps: props.viewSelectProps,
3512
+ control: { title: getWeekLabel({
3513
+ weekdays: days,
3514
+ locale: props.locale || "en",
3515
+ weekLabelFormat: props.weekLabelFormat,
3516
+ renderWeekLabel: props.renderWeekLabel ?? (slots.weekLabel ? (params) => slots.weekLabel(params) : void 0)
3517
+ }) }
3518
+ }) : null, h(Box, {
3519
+ class: WeekView_module_default.weekViewRoot,
3520
+ style: {
3521
+ "--number-of-days": String(days.length),
3522
+ "--indicator-offset-index": currentWeekdayIndex === -1 ? void 0 : String(currentWeekdayIndex + 1)
3523
+ },
3524
+ mod: { "with-weekends": props.withWeekendDays }
3525
+ }, () => [h(ScrollArea.Autosize, {
3526
+ class: WeekView_module_default.weekViewScrollArea,
3527
+ scrollbarSize: 4
3528
+ }, () => [
3529
+ h("div", { class: WeekView_module_default.weekViewHeader }, [h("div", { class: WeekView_module_default.weekViewCorner }, [withWeekNumber ? h("div", { class: WeekView_module_default.weekViewWeekLabel }, props.labels?.week || "Week") : null, withWeekNumber ? h("div", { class: WeekView_module_default.weekViewWeekNumber }, String(getWeekNumber(days))) : null]), ...days.map((date, dayIndex) => h(UnstyledButton, {
3530
+ type: "button",
3531
+ class: WeekView_module_default.weekViewDayLabel,
3532
+ "data-weekday-index": dayIndex,
3533
+ "data-weekend": props.weekendDays.includes(dayjs(date).day()) || void 0,
3534
+ "aria-label": `${getLabel("weekday", props.labels)} ${dayjs(date).format("YYYY-MM-DD")}`,
3535
+ tabindex: props.mode === "static" ? -1 : dayIndex === 0 ? 0 : -1,
3536
+ onKeydown: props.mode === "static" ? void 0 : (event) => {
3537
+ const next = event.key === "ArrowRight" ? dayIndex + 1 : event.key === "ArrowLeft" ? dayIndex - 1 : -1;
3538
+ if (next >= 0 && next < days.length) focusWeekControl(event, `[data-weekday-index="${next}"]`);
3539
+ },
3540
+ onClick: props.mode === "static" ? void 0 : () => {
3541
+ props.onViewChange?.("day");
3542
+ props.onDateChange?.(date);
3543
+ }
3544
+ }, () => [h("span", { class: WeekView_module_default.weekViewDayWeekday }, formatDate({
3545
+ date,
3546
+ locale: props.locale || "en",
3547
+ format: props.weekdayFormat
3548
+ })), h("span", {
3549
+ class: WeekView_module_default.weekViewDayNumber,
3550
+ "data-today": dayjs(date).isSame(now, "day") || void 0
3551
+ }, formatDate({
3552
+ date,
3553
+ locale: props.locale || "en",
3554
+ format: props.dayFormat
3555
+ }))]))]),
3556
+ withAllDaySlots ? h("div", { class: WeekView_module_default.weekViewAllDaySlots }, [h("div", { class: WeekView_module_default.weekViewAllDaySlotsLabel }, props.labels?.allDay || "All day"), h("div", { class: WeekView_module_default.weekViewAllDaySlotsList }, [h("div", { class: WeekView_module_default.weekViewAllDaySlotsEvents }, grouped.allDayEvents.map((event) => eventNode(event, props, {
3557
+ key: event.id,
3558
+ nowrap: true,
3559
+ hanging: event.position.hanging,
3560
+ style: {
3561
+ position: "absolute",
3562
+ insetInlineStart: `${event.position.offset}%`,
3563
+ width: `${event.position.width}%`,
3564
+ top: `${event.position.row * 22}px`
3565
+ }
3566
+ }, slots))), ...days.map((date, dayIndex) => h(UnstyledButton, {
3567
+ type: "button",
3568
+ class: WeekView_module_default.weekViewDaySlot,
3569
+ disabled: props.mode === "static",
3570
+ "data-all-day-index": dayIndex,
3571
+ "aria-label": `${getLabel("allDay", props.labels)} ${dayjs(date).format("YYYY-MM-DD")}`,
3572
+ tabindex: props.mode === "static" ? -1 : dayIndex === 0 ? 0 : -1,
3573
+ onKeydown: props.mode === "static" ? void 0 : (event) => {
3574
+ if (event.key === "ArrowDown") {
3575
+ focusWeekControl(event, `[data-week-day-index="${dayIndex}"][data-time-slot-index="0"]`);
3576
+ return;
3577
+ }
3578
+ const next = event.key === "ArrowRight" ? dayIndex + 1 : event.key === "ArrowLeft" ? dayIndex - 1 : -1;
3579
+ if (next >= 0 && next < days.length) focusWeekControl(event, `[data-all-day-index="${next}"]`);
3580
+ },
3581
+ onClick: (event) => props.onAllDaySlotClick?.(date, event),
3582
+ onDragover: (event) => event.preventDefault(),
3583
+ onDrop: (event) => emitAllDayDrop(event, date)
3584
+ }))])]) : null,
3585
+ h(Box, { class: WeekView_module_default.weekViewInner }, () => [
3586
+ h("div", { class: WeekView_module_default.weekViewSlotLabels }, intervals.map((slot) => h("div", { class: WeekView_module_default.weekViewSlotLabel }, formatDate({
3587
+ date: `${dayjs(days[0]).format("YYYY-MM-DD")} ${slot.startTime}`,
3588
+ locale: props.locale || "en",
3589
+ format: props.slotLabelFormat
3590
+ })))),
3591
+ props.withCurrentTimeIndicator && currentWeekdayIndex !== -1 ? h(CurrentTimeIndicator, {
3592
+ startOffset: "calc(100% - (100% / var(--number-of-days)) * (var(--number-of-days) - var(--indicator-offset-index) + 1) + ((var(--number-of-days) - var(--indicator-offset-index) + 1) * var(--indicator-labels-offset)))",
3593
+ endOffset: "calc((100% / var(--number-of-days)) * (var(--number-of-days) - var(--indicator-offset-index)) - (var(--number-of-days) - var(--indicator-offset-index)) * var(--indicator-labels-offset))",
3594
+ timeBubbleStartOffset: "calc(var(--week-view-slots-label-width) - var(--time-bubble-width))",
3595
+ currentTimeFormat: props.slotLabelFormat,
3596
+ withTimeBubble: props.withCurrentTimeBubble,
3597
+ withThumb: props.withCurrentTimeBubble ? currentWeekdayIndex !== 0 : true,
3598
+ locale: props.locale,
3599
+ startTime: props.startTime,
3600
+ endTime: props.endTime,
3601
+ intervalMinutes: props.intervalMinutes,
3602
+ getCurrentTime: props.getCurrentTime
3603
+ }) : null,
3604
+ ...days.map((date, dayIndex) => h("div", { class: WeekView_module_default.weekViewDay }, [h("div", {
3605
+ class: WeekView_module_default.weekViewDaySlots,
3606
+ ref: (element) => {
3607
+ if (element instanceof HTMLElement) daySlotsContainers.set(date, element);
3608
+ else daySlotsContainers.delete(date);
3609
+ },
3610
+ onDragover: withDragHandlers ? (event) => {
3611
+ event.preventDefault();
3612
+ const container = daySlotsContainers.get(date);
3613
+ if (!container) return;
3614
+ const target = getTimeSlotDropTarget({
3615
+ nativeEvent: event,
3616
+ container,
3617
+ intervals,
3618
+ date: dayjs(date).format("YYYY-MM-DD")
3619
+ });
3620
+ dropTarget.value = target ? {
3621
+ date,
3622
+ slotIndex: target.slotIndex
3623
+ } : null;
3624
+ if (event.dataTransfer) event.dataTransfer.dropEffect = event.dataTransfer.types.includes("application/json") ? "move" : "copy";
3625
+ } : void 0,
3626
+ onDragleave: withDragHandlers ? (event) => {
3627
+ const container = daySlotsContainers.get(date);
3628
+ if (!(event.relatedTarget instanceof Node) || !container?.contains(event.relatedTarget)) dropTarget.value = null;
3629
+ } : void 0,
3630
+ onDrop: withDragHandlers ? (event) => {
3631
+ const container = daySlotsContainers.get(date);
3632
+ if (!container) return;
3633
+ const target = getTimeSlotDropTarget({
3634
+ nativeEvent: event,
3635
+ container,
3636
+ intervals,
3637
+ date: dayjs(date).format("YYYY-MM-DD")
3638
+ });
3639
+ dropTarget.value = null;
3640
+ if (target) emitDrop(event, target.target);
3641
+ } : void 0
3642
+ }, [
3643
+ ...intervals.map((slot, slotIndex) => {
3644
+ const datePart = dayjs(date).format("YYYY-MM-DD");
3645
+ const start = dayjs(`${datePart} ${slot.startTime}`);
3646
+ const end = dayjs(`${datePart} ${slot.endTime}`);
3647
+ const mod = getBusinessHoursMod({
3648
+ time: slot.startTime,
3649
+ businessHours: props.businessHours || ["09:00:00", "17:00:00"],
3650
+ highlightBusinessHours: props.highlightBusinessHours,
3651
+ dayOfWeek: start.day()
3652
+ });
3653
+ return h(UnstyledButton, {
3654
+ type: "button",
3655
+ class: WeekView_module_default.weekViewDaySlot,
3656
+ "data-week-day-index": dayIndex,
3657
+ "data-time-slot-index": slotIndex,
3658
+ "data-drag-slot-index": withSlotSelect ? slotIndex : void 0,
3659
+ "data-drag-slot-group": withSlotSelect ? datePart : void 0,
3660
+ "data-drop-target": dropTarget.value?.date === date && dropTarget.value.slotIndex === slotIndex || void 0,
3661
+ "data-drag-selected": slotDragSelect.isSlotSelected(slotIndex, datePart) || void 0,
3662
+ disabled: props.mode === "static",
3663
+ "aria-label": `${getLabel("timeSlot", props.labels)} ${datePart} ${slot.startTime} - ${slot.endTime}`,
3664
+ tabindex: props.mode === "static" ? -1 : dayIndex === 0 && slotIndex === 0 ? 0 : -1,
3665
+ onKeydown: props.mode === "static" ? void 0 : (event) => {
3666
+ if (event.key === "ArrowUp" && slotIndex === 0 && withAllDaySlots) {
3667
+ focusWeekControl(event, `[data-all-day-index="${dayIndex}"]`);
3668
+ return;
3669
+ }
3670
+ const nextDay = event.key === "ArrowRight" ? dayIndex + 1 : event.key === "ArrowLeft" ? dayIndex - 1 : dayIndex;
3671
+ const nextSlot = event.key === "ArrowDown" ? slotIndex + 1 : event.key === "ArrowUp" ? slotIndex - 1 : slotIndex;
3672
+ if (nextDay >= 0 && nextDay < days.length && nextSlot >= 0 && nextSlot < intervals.length && (nextDay !== dayIndex || nextSlot !== slotIndex)) focusWeekControl(event, `[data-week-day-index="${nextDay}"][data-time-slot-index="${nextSlot}"]`);
3673
+ },
3674
+ "data-business-hours": mod["business-hours"] || void 0,
3675
+ "data-non-business-hours": mod["non-business-hours"] || void 0,
3676
+ onClick: (nativeEvent) => props.onTimeSlotClick?.({
3677
+ slotStart: start.format("YYYY-MM-DD HH:mm:ss"),
3678
+ slotEnd: end.format("YYYY-MM-DD HH:mm:ss"),
3679
+ nativeEvent
3680
+ }),
3681
+ onPointerdown: withSlotSelect ? (nativeEvent) => slotDragSelect.handleSlotPointerDown(nativeEvent, slotIndex, datePart) : void 0,
3682
+ onDragover: (event) => event.preventDefault()
3683
+ });
3684
+ }),
3685
+ ...(grouped.backgroundEvents[date] || []).map((event) => h("div", {
3686
+ class: WeekView_module_default.weekViewBackgroundEvent,
3687
+ style: {
3688
+ top: `${event.position.top}%`,
3689
+ height: `${event.position.height}%`,
3690
+ width: "100%"
3691
+ }
3692
+ })),
3693
+ ...(grouped.regularEvents[date] || []).map((event) => {
3694
+ const resizePosition = eventResize.getResizePosition(event.id);
3695
+ const isResizable = eventResize.isResizableEvent(event);
3696
+ return eventNode(event, props, {
3697
+ key: `${event.id}-${date}`,
3698
+ autoSize: true,
3699
+ style: {
3700
+ position: "absolute",
3701
+ top: `${resizePosition?.top ?? event.position.top}%`,
3702
+ height: `${resizePosition?.height ?? event.position.height}%`,
3703
+ width: `${event.position.width}%`,
3704
+ insetInlineStart: `${event.position.offset}%`
3705
+ },
3706
+ withResize: isResizable,
3707
+ isResizing: resizePosition !== null,
3708
+ onClick: props.onEventClick ? (nativeEvent) => {
3709
+ if (!eventResize.wasResizing()) props.onEventClick?.(event, nativeEvent);
3710
+ } : void 0,
3711
+ onResizeStart: (edge, pointerEvent) => {
3712
+ const container = daySlotsContainers.get(date);
3713
+ if (!container) return;
3714
+ eventResize.handleResizeStart({
3715
+ event,
3716
+ edge,
3717
+ container,
3718
+ originalTop: event.position.top,
3719
+ originalHeight: event.position.height,
3720
+ eventDate: dayjs(date).format("YYYY-MM-DD"),
3721
+ pointerEvent
3722
+ });
3723
+ }
3724
+ }, slots);
3725
+ })
3726
+ ])]))
3727
+ ])
3728
+ ])])]);
3729
+ };
3730
+ }
3731
+ });
3732
+ //#endregion
3733
+ //#region src/components/YearView/get-year-view-events/get-year-view-events.ts
3734
+ function groupEventByDate(event, groupedEvents) {
3735
+ if (isMultidayEvent(event)) {
3736
+ const startDate = dayjs(event.start).startOf("day");
3737
+ const endDate = dayjs(event.end).startOf("day");
3738
+ for (let date = startDate; date.isBefore(endDate) || date.isSame(endDate); date = date.add(1, "day")) {
3739
+ const dateKey = date.format("YYYY-MM-DD");
3740
+ if (!groupedEvents[dateKey]) groupedEvents[dateKey] = [];
3741
+ groupedEvents[dateKey].push(event);
3742
+ }
3743
+ return;
3744
+ }
3745
+ const eventDate = dayjs(event.start).format("YYYY-MM-DD");
3746
+ if (!groupedEvents[eventDate]) groupedEvents[eventDate] = [];
3747
+ groupedEvents[eventDate].push(event);
3748
+ }
3749
+ function getYearViewEvents({ date, events }) {
3750
+ const groupedEvents = {};
3751
+ if (events === void 0) return groupedEvents;
3752
+ const ids = /* @__PURE__ */ new Set();
3753
+ for (const event of events) if (dayjs(event.start).isSame(dayjs(date), "year")) {
3754
+ groupEventByDate(validateEvent(event), groupedEvents);
3755
+ if (!ids.has(event.id)) ids.add(event.id);
3756
+ else throw new Error(`[@mantine/schedule] YearView: Duplicated event ids found: ${event.id}`);
3757
+ }
3758
+ return groupedEvents;
3759
+ }
3760
+ var YearView_module_default = {
3761
+ yearView: "_yearView_1y6ar_1",
3762
+ yearViewMonths: "_yearViewMonths_1y6ar_15",
3763
+ yearViewMonth: "_yearViewMonth_1y6ar_15",
3764
+ yearViewWeekdays: "_yearViewWeekdays_1y6ar_92",
3765
+ yearViewWeek: "_yearViewWeek_1y6ar_92",
3766
+ yearViewWeekNumber: "_yearViewWeekNumber_1y6ar_100",
3767
+ yearViewWeekday: "_yearViewWeekday_1y6ar_92",
3768
+ yearViewWeekdaysCorner: "_yearViewWeekdaysCorner_1y6ar_154",
3769
+ yearViewDay: "_yearViewDay_1y6ar_158",
3770
+ yearViewMonthCaption: "_yearViewMonthCaption_1y6ar_217",
3771
+ yearViewDayIndicators: "_yearViewDayIndicators_1y6ar_243",
3772
+ yearViewDayIndicator: "_yearViewDayIndicator_1y6ar_243"
3773
+ };
3774
+ //#endregion
3775
+ //#region src/components/YearView/YearView.ts
3776
+ var YearView = defineComponent({
3777
+ name: "YearView",
3778
+ inheritAttrs: false,
3779
+ props: {
3780
+ ...baseViewProps,
3781
+ firstDayOfWeek: {
3782
+ type: Number,
3783
+ default: 1
3784
+ },
3785
+ weekdayFormat: {
3786
+ type: [String, Function],
3787
+ default: "dd"
3788
+ },
3789
+ weekendDays: {
3790
+ type: Array,
3791
+ default: () => [0, 6]
3792
+ },
3793
+ withWeekNumbers: Boolean,
3794
+ withWeekDays: {
3795
+ type: Boolean,
3796
+ default: true
3797
+ },
3798
+ consistentWeeks: Boolean,
3799
+ highlightToday: {
3800
+ type: Boolean,
3801
+ default: true
3802
+ },
3803
+ withOutsideDays: {
3804
+ type: Boolean,
3805
+ default: true
3806
+ },
3807
+ monthsListFormat: {
3808
+ type: [String, Function],
3809
+ default: "MMMM"
3810
+ },
3811
+ getDayProps: Function,
3812
+ getWeekNumberProps: Function,
3813
+ onDayClick: Function,
3814
+ onMonthClick: Function,
3815
+ onWeekNumberClick: Function
3816
+ },
3817
+ setup(props, { attrs }) {
3818
+ const yearGrid = ref(null);
3819
+ return () => {
3820
+ const year = dayjs(props.date).startOf("year");
3821
+ const eventsByDay = getYearViewEvents({
3822
+ date: year,
3823
+ events: getExpandedEvents(props.events, year.startOf("year").format("YYYY-MM-DD HH:mm:ss"), year.endOf("year").format("YYYY-MM-DD HH:mm:ss"), props.recurrenceExpansionLimit)
3824
+ });
3825
+ const weekdays = getWeekdaysNames({
3826
+ locale: props.locale || "en",
3827
+ format: props.weekdayFormat,
3828
+ firstDayOfWeek: props.firstDayOfWeek
3829
+ });
3830
+ let totalYearGridCells = 0;
3831
+ const months = Array.from({ length: 12 }, (_, monthIndex) => {
3832
+ const month = year.month(monthIndex);
3833
+ const weeks = getMonthDays({
3834
+ month,
3835
+ firstDayOfWeek: props.firstDayOfWeek,
3836
+ consistentWeeks: props.consistentWeeks
3837
+ });
3838
+ const offset = totalYearGridCells;
3839
+ totalYearGridCells += weeks.length * 7;
3840
+ return {
3841
+ month,
3842
+ monthIndex,
3843
+ weeks,
3844
+ offset
3845
+ };
3846
+ });
3847
+ return h(Box, {
3848
+ ...attrs,
3849
+ class: [YearView_module_default.yearView, attrs.class],
3850
+ style: [{ "--year-view-radius": resolveScheduleRadius(props.radius) }, attrs.style]
3851
+ }, () => [props.withHeader ? h(ScheduleHeaderBase, {
3852
+ view: "year",
3853
+ labels: props.labels,
3854
+ onDateChange: props.onDateChange,
3855
+ onViewChange: props.onViewChange,
3856
+ navigationHandlers: createHeaderNavigation(props.date, "year"),
3857
+ previousControlProps: props.previousControlProps,
3858
+ nextControlProps: props.nextControlProps,
3859
+ todayControlProps: props.todayControlProps,
3860
+ viewSelectProps: props.viewSelectProps,
3861
+ control: { monthYearSelect: {
3862
+ locale: props.locale,
3863
+ yearValue: year.year(),
3864
+ withMonths: false,
3865
+ labelFormat: "YYYY",
3866
+ onYearChange: (value) => props.onDateChange?.(toDateString(year.year(value)))
3867
+ } }
3868
+ }) : null, h("div", {
3869
+ ref: yearGrid,
3870
+ class: YearView_module_default.yearViewMonths
3871
+ }, months.map(({ month, weeks, offset }) => {
3872
+ return h("section", {
3873
+ class: YearView_module_default.yearViewMonth,
3874
+ "data-with-week-numbers": props.withWeekNumbers || void 0
3875
+ }, [
3876
+ h(UnstyledButton, {
3877
+ type: "button",
3878
+ class: YearView_module_default.yearViewMonthCaption,
3879
+ onClick: () => props.onMonthClick?.(toDateString(month))
3880
+ }, () => formatDate({
3881
+ date: month,
3882
+ locale: props.locale || "en",
3883
+ format: props.monthsListFormat
3884
+ })),
3885
+ props.withWeekDays ? h("div", { class: YearView_module_default.yearViewWeekdays }, [props.withWeekNumbers ? h("span", { class: YearView_module_default.yearViewWeekdaysCorner }) : null, ...weekdays.map((weekday) => h("span", { class: YearView_module_default.yearViewWeekday }, [weekday]))]) : null,
3886
+ ...weeks.map((week, weekIndex) => h("div", { class: YearView_module_default.yearViewWeek }, [props.withWeekNumbers ? h(UnstyledButton, {
3887
+ type: "button",
3888
+ class: YearView_module_default.yearViewWeekNumber,
3889
+ ...props.getWeekNumberProps?.(toDateString(week[0])),
3890
+ onClick: (event) => props.onWeekNumberClick?.(toDateString(week[0]), event)
3891
+ }, () => String(getWeekNumber(week))) : null, ...week.map((date, dayIndex) => {
3892
+ const events = eventsByDay[dayjs(date).format("YYYY-MM-DD")] || [];
3893
+ const outside = !dayjs(date).isSame(month, "month");
3894
+ const gridIndex = offset + weekIndex * 7 + dayIndex;
3895
+ const extra = props.getDayProps?.(toDateString(date)) || {};
3896
+ if (outside && !props.withOutsideDays) return h("div", {
3897
+ class: YearView_module_default.yearViewDay,
3898
+ "data-day-placeholder": true,
3899
+ key: toDateString(date)
3900
+ });
3901
+ return h(UnstyledButton, {
3902
+ type: "button",
3903
+ ...extra,
3904
+ class: [YearView_module_default.yearViewDay, extra.class],
3905
+ disabled: props.mode === "static",
3906
+ "data-year-grid-index": gridIndex,
3907
+ "data-outside": outside || void 0,
3908
+ "data-weekend": props.weekendDays.includes(dayjs(date).day()) || void 0,
3909
+ "data-today": props.highlightToday && dayjs(date).isSame(dayjs(), "day") || void 0,
3910
+ "aria-label": formatDate({
3911
+ date,
3912
+ locale: props.locale || "en",
3913
+ format: "MMMM D, YYYY"
3914
+ }),
3915
+ tabindex: props.mode === "static" || outside ? -1 : dayjs(date).date() === 1 ? 0 : -1,
3916
+ onKeydown: props.mode === "static" ? void 0 : (event) => {
3917
+ handleGridKeydown({
3918
+ event,
3919
+ index: gridIndex,
3920
+ columns: 7,
3921
+ total: totalYearGridCells,
3922
+ getControl: (index) => {
3923
+ const control = yearGrid.value?.querySelector(`[data-year-grid-index="${index}"]`) ?? null;
3924
+ return control?.hasAttribute("data-outside") ? null : control;
3925
+ }
3926
+ });
3927
+ extra.onKeydown?.(event);
3928
+ },
3929
+ onClick: (event) => props.onDayClick?.(toDateString(date), event)
3930
+ }, () => [String(dayjs(date).date()), events.length ? h("span", { class: YearView_module_default.yearViewDayIndicators }, events.slice(0, 3).map((event) => h("span", {
3931
+ class: YearView_module_default.yearViewDayIndicator,
3932
+ style: { background: `var(--mantine-color-${event.color}-6, ${event.color})` }
3933
+ }))) : null]);
3934
+ })]))
3935
+ ]);
3936
+ }))]);
3937
+ };
3938
+ }
3939
+ });
3940
+ var Schedule_module_default = {
3941
+ root: "_root_j1q6m_1",
3942
+ desktopView: "_desktopView_j1q6m_7",
3943
+ mobileView: "_mobileView_j1q6m_16"
3944
+ };
3945
+ //#endregion
3946
+ //#region src/components/Schedule/Schedule.ts
3947
+ var Schedule = defineComponent({
3948
+ name: "Schedule",
3949
+ inheritAttrs: false,
3950
+ slots: Object,
3951
+ props: {
3952
+ date: [String, Date],
3953
+ defaultDate: [String, Date],
3954
+ onDateChange: Function,
3955
+ view: String,
3956
+ defaultView: {
3957
+ type: String,
3958
+ default: "week"
3959
+ },
3960
+ onViewChange: Function,
3961
+ events: Array,
3962
+ locale: String,
3963
+ radius: [String, Number],
3964
+ labels: Object,
3965
+ renderEventBody: Function,
3966
+ withEventsDragAndDrop: Boolean,
3967
+ onEventDrop: Function,
3968
+ canDragEvent: Function,
3969
+ onEventDragStart: Function,
3970
+ onEventDragEnd: Function,
3971
+ onTimeSlotClick: Function,
3972
+ onAllDaySlotClick: Function,
3973
+ onEventClick: Function,
3974
+ onDayClick: Function,
3975
+ onMonthClick: Function,
3976
+ withDragSlotSelect: Boolean,
3977
+ onSlotDragEnd: Function,
3978
+ mode: {
3979
+ type: String,
3980
+ default: "default"
3981
+ },
3982
+ onExternalEventDrop: Function,
3983
+ withEventResize: Boolean,
3984
+ onEventResize: Function,
3985
+ canResizeEvent: Function,
3986
+ recurrenceExpansionLimit: {
3987
+ type: Number,
3988
+ default: 2e3
3989
+ },
3990
+ layout: {
3991
+ type: String,
3992
+ default: "default"
3993
+ },
3994
+ dayViewProps: Object,
3995
+ weekViewProps: Object,
3996
+ monthViewProps: Object,
3997
+ yearViewProps: Object,
3998
+ mobileMonthViewProps: Object
3999
+ },
4000
+ setup(props, { attrs, slots }) {
4001
+ const currentDate = ref(toDateString(props.date || props.defaultDate || dayjs()));
4002
+ const currentView = ref(props.view || props.defaultView);
4003
+ watch(() => props.date, (value) => {
4004
+ if (value !== void 0) currentDate.value = toDateString(value);
4005
+ });
4006
+ watch(() => props.view, (value) => {
4007
+ if (value !== void 0) currentView.value = value;
4008
+ });
4009
+ const changeDate = (date) => {
4010
+ if (props.date === void 0) currentDate.value = date;
4011
+ props.onDateChange?.(date);
4012
+ };
4013
+ const changeView = (view) => {
4014
+ if (props.view === void 0) currentView.value = view;
4015
+ props.onViewChange?.(view);
4016
+ };
4017
+ return () => {
4018
+ const shared = {
4019
+ date: currentDate.value,
4020
+ onDateChange: changeDate,
4021
+ onViewChange: changeView,
4022
+ events: props.events,
4023
+ locale: props.locale,
4024
+ radius: props.radius,
4025
+ labels: props.labels,
4026
+ renderEventBody: props.renderEventBody,
4027
+ withEventsDragAndDrop: props.withEventsDragAndDrop,
4028
+ onEventDrop: props.onEventDrop,
4029
+ canDragEvent: props.canDragEvent,
4030
+ onEventDragStart: props.onEventDragStart,
4031
+ onEventDragEnd: props.onEventDragEnd,
4032
+ onTimeSlotClick: props.onTimeSlotClick,
4033
+ onAllDaySlotClick: props.onAllDaySlotClick,
4034
+ onEventClick: props.onEventClick,
4035
+ onDayClick: props.onDayClick,
4036
+ onMonthClick: props.onMonthClick,
4037
+ withDragSlotSelect: props.withDragSlotSelect,
4038
+ onSlotDragEnd: props.onSlotDragEnd,
4039
+ mode: props.mode,
4040
+ onExternalEventDrop: props.onExternalEventDrop,
4041
+ withEventResize: props.withEventResize,
4042
+ onEventResize: props.onEventResize,
4043
+ canResizeEvent: props.canResizeEvent,
4044
+ recurrenceExpansionLimit: props.recurrenceExpansionLimit
4045
+ };
4046
+ const components = {
4047
+ day: [DayView, props.dayViewProps],
4048
+ week: [WeekView, props.weekViewProps],
4049
+ month: [MonthView, props.monthViewProps],
4050
+ year: [YearView, props.yearViewProps]
4051
+ };
4052
+ const viewSlots = {};
4053
+ if (slots.eventBody) viewSlots.eventBody = slots.eventBody;
4054
+ if (slots.event) viewSlots.event = slots.event;
4055
+ if (slots.weekLabel) viewSlots.weekLabel = slots.weekLabel;
4056
+ if (slots.header) viewSlots.header = slots.header;
4057
+ const forwardedSlots = Object.keys(viewSlots).length ? viewSlots : void 0;
4058
+ const [component, viewProps] = components[currentView.value];
4059
+ const desktop = h(component, {
4060
+ ...shared,
4061
+ ...viewProps
4062
+ }, forwardedSlots);
4063
+ if (props.layout !== "responsive") return h(Box, {
4064
+ ...attrs,
4065
+ class: [Schedule_module_default.root, attrs.class],
4066
+ style: attrs.style
4067
+ }, () => [desktop]);
4068
+ const mobile = currentView.value === "year" ? h(YearView, {
4069
+ ...shared,
4070
+ ...props.yearViewProps
4071
+ }, forwardedSlots) : h(MobileMonthView, {
4072
+ ...shared,
4073
+ ...props.mobileMonthViewProps,
4074
+ onYearClick: () => changeView("year"),
4075
+ onDayClick: (date, event) => {
4076
+ props.onDayClick?.(date, event);
4077
+ props.mobileMonthViewProps?.onDayClick?.(date, event);
4078
+ }
4079
+ }, forwardedSlots);
4080
+ return h(Box, {
4081
+ ...attrs,
4082
+ mod: { layout: props.layout },
4083
+ class: [Schedule_module_default.root, attrs.class],
4084
+ style: attrs.style
4085
+ }, () => [h(Box, { class: Schedule_module_default.desktopView }, () => [desktop]), h(Box, { class: Schedule_module_default.mobileView }, () => [mobile])]);
4086
+ };
4087
+ }
4088
+ });
4089
+ //#endregion
4090
+ //#region src/components/DragContext/DragContext.ts
4091
+ var DragContext = Symbol("mantine-schedule-drag-context");
4092
+ function provideDragContext(value) {
4093
+ provide(DragContext, value);
4094
+ }
4095
+ function useDragContext() {
4096
+ return inject(DragContext, {
4097
+ draggedEvent: null,
4098
+ dragOverTarget: null,
4099
+ isDragging: false,
4100
+ isSlotDragging: false
4101
+ });
4102
+ }
4103
+ //#endregion
4104
+ export { CurrentTimeIndicator, DEFAULT_SCHEDULE_LABELS, DayView, DragContext, HeaderControl, MobileMonthView, MonthView, MonthYearSelect, MoreEvents, Schedule, ScheduleEvent, ScheduleHeader, ScheduleHeaderBase, ScheduleHeaderNext, ScheduleHeaderPrevious, ScheduleHeaderToday, ViewSelect, WeekView, YearView, calculateDropTime, calculateMonthDropDate, clampIntervalMinutes, createHeaderNavigation, expandRecurringEvents, formatDate, getBusinessHoursMod, getCurrentTimePosition, getDayPosition, getDayPositionedEvents, getDayTimeIntervals, getDayViewEvents, getEndOfWeek, getLabel, getMonthDays, getMonthPositionedEvents, getMonthRange, getMonthViewEvents, getMonthsByQuarter, getMonthsList, getRenderableMonthEventSegments, getStartOfWeek, getVisibleEvents, getWeekDays, getWeekLabel, getWeekNumber, getWeekPositionedEvents, getWeekViewEvents, getWeekdaysNames, getYearsList, isAfterMinDate, isAllDayEvent, isBeforeMaxDate, isEventInTimeRange, isEventsOverlap, isInTimeRange, isMultidayEvent, isSameMonth, isWithinWeek, nextWeek, parseTimeString, previousWeek, provideDragContext, sortEvents, toDateString, toTimeString, useDragContext, validateEvent };
4105
+
4106
+ //# sourceMappingURL=index.mjs.map