@mantine-vue/schedule 3.5.0 → 3.7.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 (29) hide show
  1. package/cjs/index.cjs +925 -185
  2. package/cjs/index.cjs.map +1 -1
  3. package/esm/index.mjs +925 -186
  4. package/esm/index.mjs.map +1 -1
  5. package/lib/component-props.d.ts +11 -1
  6. package/lib/components/DayView/DayView.vue.d.ts +2 -0
  7. package/lib/components/MonthView/MonthView.types.d.ts +9 -1
  8. package/lib/components/MonthView/MonthView.vue.d.ts +2 -0
  9. package/lib/components/MonthView/get-month-view-events/reserve-row.d.ts +7 -0
  10. package/lib/components/ResourcesDayView/ResourcesDayView.types.d.ts +10 -1
  11. package/lib/components/ResourcesDayView/ResourcesDayView.vue.d.ts +2 -0
  12. package/lib/components/ResourcesMonthView/ResourcesMonthView.types.d.ts +10 -1
  13. package/lib/components/ResourcesMonthView/ResourcesMonthView.vue.d.ts +2 -0
  14. package/lib/components/ResourcesSchedule/ResourcesSchedule.types.d.ts +10 -1
  15. package/lib/components/ResourcesSchedule/ResourcesSchedule.vue.d.ts +2 -0
  16. package/lib/components/ResourcesWeekView/ResourcesWeekView.types.d.ts +10 -1
  17. package/lib/components/ResourcesWeekView/ResourcesWeekView.vue.d.ts +2 -0
  18. package/lib/components/Schedule/Schedule.types.d.ts +11 -1
  19. package/lib/components/Schedule/Schedule.vue.d.ts +2 -0
  20. package/lib/components/WeekView/WeekView.vue.d.ts +2 -0
  21. package/lib/hooks/use-event-resize.d.ts +6 -1
  22. package/lib/hooks/use-horizontal-event-resize.d.ts +6 -0
  23. package/lib/hooks/validate-event-resize.d.ts +26 -0
  24. package/lib/types.d.ts +38 -0
  25. package/lib/utils/index.d.ts +2 -0
  26. package/lib/utils/is-event-placement-allowed/is-event-placement-allowed.d.ts +13 -0
  27. package/package.json +4 -4
  28. package/styles.css +494 -441
  29. package/styles.layer.css +494 -441
package/esm/index.mjs CHANGED
@@ -358,6 +358,45 @@ function isEventsOverlap(event1, event2) {
358
358
  return first.startTimestamp < second.endTimestamp && second.startTimestamp < first.endTimestamp;
359
359
  }
360
360
  //#endregion
361
+ //#region src/utils/is-event-placement-allowed/is-event-placement-allowed.ts
362
+ function isSameEvent(event, other) {
363
+ if (event.id === other.id) return true;
364
+ const eventSeriesId = event.recurringEventId ?? event.recurringInstance?.recurringEventId;
365
+ const otherSeriesId = other.recurringEventId ?? other.recurringInstance?.recurringEventId;
366
+ const eventOccurrenceId = event.recurrenceId ?? event.recurringInstance?.recurrenceId;
367
+ const otherOccurrenceId = other.recurrenceId ?? other.recurringInstance?.recurrenceId;
368
+ return eventSeriesId !== void 0 && eventSeriesId === otherSeriesId && eventOccurrenceId !== void 0 && eventOccurrenceId === otherOccurrenceId;
369
+ }
370
+ var isMidnight = (value) => value.hour() === 0 && value.minute() === 0 && value.second() === 0;
371
+ function spansWholeDays(event) {
372
+ const start = dayjs(event.start);
373
+ const end = dayjs(event.end);
374
+ return isMidnight(start) && (isMidnight(end) || end.hour() === 23 && end.minute() === 59 && end.second() === 59);
375
+ }
376
+ function isEventPlacementAllowed({ event, start, end, events, preventEventOverlap, resourceId }) {
377
+ if (!preventEventOverlap) return {
378
+ allowed: true,
379
+ conflicts: []
380
+ };
381
+ const candidate = {
382
+ ...event,
383
+ start,
384
+ end,
385
+ ...resourceId !== void 0 ? { resourceId } : {}
386
+ };
387
+ const allDay = spansWholeDays(candidate);
388
+ const conflicts = events.filter((other) => {
389
+ if (other.display === "background" || isSameEvent(event, other)) return false;
390
+ if (resourceId !== void 0 && other.resourceId !== resourceId) return false;
391
+ if (spansWholeDays(other) !== allDay || !isEventsOverlap(other, candidate)) return false;
392
+ return typeof preventEventOverlap === "function" ? preventEventOverlap(other, candidate) : true;
393
+ });
394
+ return {
395
+ allowed: conflicts.length === 0,
396
+ conflicts
397
+ };
398
+ }
399
+ //#endregion
361
400
  //#region src/utils/get-visible-events/get-visible-events.ts
362
401
  function getVisibleEvents({ maxEvents, totalEvents }) {
363
402
  if (totalEvents <= maxEvents) return {
@@ -930,9 +969,42 @@ function moveEventToAllDay(event, date) {
930
969
  };
931
970
  }
932
971
  //#endregion
972
+ //#region src/hooks/validate-event-resize.ts
973
+ function validateEventResize({ event, start, end, edge, events = [], preventEventOverlap, canResizeEventTo, resourceId }) {
974
+ const { allowed, conflicts } = isEventPlacementAllowed({
975
+ event,
976
+ start,
977
+ end,
978
+ events,
979
+ preventEventOverlap,
980
+ resourceId
981
+ });
982
+ if (!allowed) return {
983
+ valid: false,
984
+ conflicts,
985
+ reason: "overlap"
986
+ };
987
+ if (canResizeEventTo?.({
988
+ event,
989
+ start,
990
+ end,
991
+ edge
992
+ }) === false) return {
993
+ valid: false,
994
+ conflicts: [],
995
+ reason: "rejected"
996
+ };
997
+ return {
998
+ valid: true,
999
+ conflicts: [],
1000
+ reason: null
1001
+ };
1002
+ }
1003
+ //#endregion
933
1004
  //#region src/hooks/use-event-resize.ts
934
1005
  function useEventResize(input) {
935
1006
  const resizeState = shallowRef(null);
1007
+ const resizeValid = shallowRef(true);
936
1008
  let justResized = false;
937
1009
  let savedUserSelect = null;
938
1010
  const clampAndSnap = (minutes, state) => {
@@ -974,6 +1046,18 @@ function useEventResize(input) {
974
1046
  currentTop,
975
1047
  currentHeight
976
1048
  };
1049
+ const next = resizeState.value;
1050
+ const start = next.edge === "top" ? percentToDateTime(next.currentTop, next.eventDate, next) : next.originalStart;
1051
+ const end = next.edge === "bottom" ? percentToDateTime(next.currentTop + next.currentHeight, next.eventDate, next) : next.originalEnd;
1052
+ resizeValid.value = validateEventResize({
1053
+ event: next.event,
1054
+ start,
1055
+ end,
1056
+ edge: next.edge === "top" ? "start" : "end",
1057
+ events: input.events?.() ?? [],
1058
+ preventEventOverlap: input.preventEventOverlap?.(),
1059
+ canResizeEventTo: input.canResizeEventTo?.()
1060
+ }).valid;
977
1061
  });
978
1062
  const trackPointer = (event) => handlePointerMove(event.clientY);
979
1063
  const removeDocumentListeners = () => {
@@ -991,14 +1075,34 @@ function useEventResize(input) {
991
1075
  if (state && (state.currentTop !== state.originalTop || state.currentHeight !== state.originalHeight)) {
992
1076
  const newStart = state.edge === "top" ? percentToDateTime(state.currentTop, state.eventDate, state) : state.originalStart;
993
1077
  const newEnd = state.edge === "bottom" ? percentToDateTime(state.currentTop + state.currentHeight, state.eventDate, state) : state.originalEnd;
994
- input.onEventResize({
1078
+ const edge = state.edge === "top" ? "start" : "end";
1079
+ const validation = validateEventResize({
1080
+ event: state.event,
1081
+ start: newStart,
1082
+ end: newEnd,
1083
+ edge,
1084
+ events: input.events?.() ?? [],
1085
+ preventEventOverlap: input.preventEventOverlap?.(),
1086
+ canResizeEventTo: input.canResizeEventTo?.()
1087
+ });
1088
+ if (validation.valid) input.onEventResize({
995
1089
  eventId: state.eventId,
996
1090
  newStart,
997
1091
  newEnd,
998
1092
  event: state.event
999
1093
  });
1094
+ else input.onEventPlacementRejected?.({
1095
+ action: "resize",
1096
+ event: state.event,
1097
+ start: newStart,
1098
+ end: newEnd,
1099
+ edge,
1100
+ conflicts: validation.conflicts,
1101
+ reason: validation.reason
1102
+ });
1000
1103
  }
1001
1104
  resizeState.value = null;
1105
+ resizeValid.value = true;
1002
1106
  removeDocumentListeners();
1003
1107
  justResized = true;
1004
1108
  requestAnimationFrame(() => {
@@ -1034,6 +1138,7 @@ function useEventResize(input) {
1034
1138
  intervalMinutes,
1035
1139
  minHeightPercent: intervalMinutes / totalMinutes * 100
1036
1140
  };
1141
+ resizeValid.value = true;
1037
1142
  savedUserSelect = document.body.style.userSelect;
1038
1143
  document.body.style.userSelect = "none";
1039
1144
  document.addEventListener("pointermove", trackPointer);
@@ -1054,7 +1159,8 @@ function useEventResize(input) {
1054
1159
  resizingEventId: computed(() => resizeState.value?.eventId ?? null),
1055
1160
  getResizePosition,
1056
1161
  isResizableEvent,
1057
- wasResizing: () => justResized
1162
+ wasResizing: () => justResized,
1163
+ resizeValid: computed(() => resizeValid.value)
1058
1164
  };
1059
1165
  }
1060
1166
  var CurrentTimeIndicator_module_default = {
@@ -1274,9 +1380,9 @@ function provideScheduleDragState(input = {}) {
1274
1380
  };
1275
1381
  }
1276
1382
  var ScheduleEvent_module_default = {
1277
- event: "_event_ho258_1",
1278
- eventInner: "_eventInner_ho258_14",
1279
- eventResizeHandle: "_eventResizeHandle_ho258_210"
1383
+ event: "_event_iymqv_1",
1384
+ eventInner: "_eventInner_iymqv_14",
1385
+ eventResizeHandle: "_eventResizeHandle_iymqv_215"
1280
1386
  };
1281
1387
  //#endregion
1282
1388
  //#region src/components/ScheduleEvent/ScheduleEvent.vue?vue&type=script&setup=true&lang.ts
@@ -2942,19 +3048,19 @@ function getDayViewEvents({ events, date, startTime, endTime, intervalMinutes, e
2942
3048
  };
2943
3049
  }
2944
3050
  var DayView_module_default = {
2945
- dayView: "_dayView_10v37_1",
2946
- dayViewDragPreview: "_dayViewDragPreview_10v37_13",
2947
- dayViewScrollArea: "_dayViewScrollArea_10v37_31",
2948
- dayViewInner: "_dayViewInner_10v37_41",
2949
- dayViewTimeSlots: "_dayViewTimeSlots_10v37_45",
2950
- dayViewSlot: "_dayViewSlot_10v37_48",
2951
- dayViewSlotLabels: "_dayViewSlotLabels_10v37_53",
2952
- dayViewSlotLabel: "_dayViewSlotLabel_10v37_53",
2953
- dayViewSlots: "_dayViewSlots_10v37_83",
2954
- dayViewBackgroundEvent: "_dayViewBackgroundEvent_10v37_187",
2955
- dayViewBackgroundEventResizeHandle: "_dayViewBackgroundEventResizeHandle_10v37_216",
2956
- dayViewAllDay: "_dayViewAllDay_10v37_263",
2957
- dayViewAllDayEvents: "_dayViewAllDayEvents_10v37_268"
3051
+ dayView: "_dayView_18224_1",
3052
+ dayViewDragPreview: "_dayViewDragPreview_18224_13",
3053
+ dayViewScrollArea: "_dayViewScrollArea_18224_31",
3054
+ dayViewInner: "_dayViewInner_18224_41",
3055
+ dayViewTimeSlots: "_dayViewTimeSlots_18224_45",
3056
+ dayViewSlot: "_dayViewSlot_18224_48",
3057
+ dayViewSlotLabels: "_dayViewSlotLabels_18224_53",
3058
+ dayViewSlotLabel: "_dayViewSlotLabel_18224_53",
3059
+ dayViewSlots: "_dayViewSlots_18224_83",
3060
+ dayViewBackgroundEvent: "_dayViewBackgroundEvent_18224_196",
3061
+ dayViewBackgroundEventResizeHandle: "_dayViewBackgroundEventResizeHandle_18224_225",
3062
+ dayViewAllDay: "_dayViewAllDay_18224_272",
3063
+ dayViewAllDayEvents: "_dayViewAllDayEvents_18224_277"
2958
3064
  };
2959
3065
  //#endregion
2960
3066
  //#region src/components/DayView/DayView.vue?vue&type=script&setup=true&lang.ts
@@ -3028,6 +3134,9 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3028
3134
  type: Function,
3029
3135
  default: void 0
3030
3136
  },
3137
+ canDropEvent: {},
3138
+ canDropExternalEvent: {},
3139
+ preventEventOverlap: { type: [Boolean, Function] },
3031
3140
  withDragSlotSelect: { type: Boolean },
3032
3141
  withExternalEventDrop: { type: Boolean },
3033
3142
  startScrollTime: { default: void 0 },
@@ -3036,6 +3145,7 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3036
3145
  type: Function,
3037
3146
  default: void 0
3038
3147
  },
3148
+ canResizeEventTo: {},
3039
3149
  date: {},
3040
3150
  events: { default: void 0 },
3041
3151
  locale: { default: void 0 },
@@ -3077,6 +3187,7 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3077
3187
  "slotDragEnd",
3078
3188
  "externalEventDrop",
3079
3189
  "eventResize",
3190
+ "eventPlacementRejected",
3080
3191
  "dateChange",
3081
3192
  "viewChange",
3082
3193
  "eventClick"
@@ -3117,6 +3228,7 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3117
3228
  const eventRenderers = computed(() => resolveEventRenderers(props, slots));
3118
3229
  const timeSlotsContainer = ref(null);
3119
3230
  const slotDropTarget = useSlotDropTarget();
3231
+ const dropDataTransfer = shallowRef(null);
3120
3232
  const date = computed(() => toDateString(props.date));
3121
3233
  const datePart = computed(() => dayjs(date.value).format("YYYY-MM-DD"));
3122
3234
  const now = computed(() => dayjs(props.getCurrentTime?.() ?? dayjs()));
@@ -3153,6 +3265,10 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3153
3265
  resizeIntervalMinutes: () => props.eventResizeInterval,
3154
3266
  onEventResize: (data) => emit("eventResize", data),
3155
3267
  canResizeEvent: () => props.canResizeEvent,
3268
+ events: () => expandedEvents.value,
3269
+ preventEventOverlap: () => props.preventEventOverlap,
3270
+ canResizeEventTo: () => props.canResizeEventTo,
3271
+ onEventPlacementRejected: (data) => emit("eventPlacementRejected", data),
3156
3272
  withBackgroundEvents: () => Boolean(props.withInteractiveBackgroundEvents)
3157
3273
  });
3158
3274
  const slotDragSelect = useSlotDragSelect({
@@ -3175,9 +3291,35 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3175
3291
  isSlotDragging: () => slotDragSelect.isDragging(),
3176
3292
  onDragEnd: () => {
3177
3293
  slotDropTarget.reset();
3294
+ dropDataTransfer.value = null;
3178
3295
  emit("eventDragEnd");
3179
3296
  }
3180
3297
  });
3298
+ const dropValid = computed(() => {
3299
+ const target = slotDropTarget.dropTarget.value;
3300
+ const interval = target && intervals.value[target.slotIndex];
3301
+ if (!target || !interval) return true;
3302
+ const start = `${target.date} ${interval.startTime}`;
3303
+ const event = dragState.draggedEvent.value;
3304
+ if (event) {
3305
+ const next = moveEventTo(event, start);
3306
+ return isEventPlacementAllowed({
3307
+ event,
3308
+ start: next.newStart,
3309
+ end: next.newEnd,
3310
+ events: expandedEvents.value,
3311
+ preventEventOverlap: props.preventEventOverlap
3312
+ }).allowed && props.canDropEvent?.({
3313
+ event,
3314
+ start: next.newStart,
3315
+ end: next.newEnd
3316
+ }) !== false;
3317
+ }
3318
+ return dropDataTransfer.value ? props.canDropExternalEvent?.({
3319
+ dataTransfer: dropDataTransfer.value,
3320
+ start
3321
+ }) !== false : true;
3322
+ });
3181
3323
  onMounted(async () => {
3182
3324
  if (!props.startScrollTime) return;
3183
3325
  await nextTick();
@@ -3195,14 +3337,79 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3195
3337
  const emitDrop = (nativeEvent, target) => {
3196
3338
  nativeEvent.preventDefault();
3197
3339
  const event = getDropEvent(expandedEvents.value, nativeEvent.dataTransfer);
3198
- if (event) emit("eventDrop", moveEventTo(event, target));
3199
- else if (nativeEvent.dataTransfer) emit("externalEventDrop", nativeEvent.dataTransfer, target);
3340
+ if (event) {
3341
+ const next = moveEventTo(event, target);
3342
+ const validation = isEventPlacementAllowed({
3343
+ event,
3344
+ start: next.newStart,
3345
+ end: next.newEnd,
3346
+ events: expandedEvents.value,
3347
+ preventEventOverlap: props.preventEventOverlap
3348
+ });
3349
+ if (validation.allowed && props.canDropEvent?.({
3350
+ event,
3351
+ start: next.newStart,
3352
+ end: next.newEnd
3353
+ }) !== false) emit("eventDrop", next);
3354
+ else emit("eventPlacementRejected", {
3355
+ action: "drop",
3356
+ event,
3357
+ start: next.newStart,
3358
+ end: next.newEnd,
3359
+ conflicts: validation.conflicts,
3360
+ reason: validation.allowed ? "rejected" : "overlap"
3361
+ });
3362
+ } else if (nativeEvent.dataTransfer) if (props.canDropExternalEvent?.({
3363
+ dataTransfer: nativeEvent.dataTransfer,
3364
+ start: target
3365
+ }) !== false) emit("externalEventDrop", nativeEvent.dataTransfer, target);
3366
+ else emit("eventPlacementRejected", {
3367
+ action: "external-drop",
3368
+ dataTransfer: nativeEvent.dataTransfer,
3369
+ start: target,
3370
+ conflicts: [],
3371
+ reason: "rejected"
3372
+ });
3200
3373
  };
3201
3374
  const emitAllDayDrop = (nativeEvent) => {
3202
3375
  nativeEvent.preventDefault();
3203
3376
  const event = getDropEvent(expandedEvents.value, nativeEvent.dataTransfer);
3204
- if (event) emit("eventDrop", moveEventToAllDay(event, datePart.value));
3205
- else if (nativeEvent.dataTransfer) emit("externalEventDrop", nativeEvent.dataTransfer, `${datePart.value} 00:00:00`);
3377
+ if (event) {
3378
+ const next = moveEventToAllDay(event, datePart.value);
3379
+ const validation = isEventPlacementAllowed({
3380
+ event,
3381
+ start: next.newStart,
3382
+ end: next.newEnd,
3383
+ events: expandedEvents.value,
3384
+ preventEventOverlap: props.preventEventOverlap
3385
+ });
3386
+ if (validation.allowed && props.canDropEvent?.({
3387
+ event,
3388
+ start: next.newStart,
3389
+ end: next.newEnd
3390
+ }) !== false) emit("eventDrop", next);
3391
+ else emit("eventPlacementRejected", {
3392
+ action: "drop",
3393
+ event,
3394
+ start: next.newStart,
3395
+ end: next.newEnd,
3396
+ conflicts: validation.conflicts,
3397
+ reason: validation.allowed ? "rejected" : "overlap"
3398
+ });
3399
+ } else if (nativeEvent.dataTransfer) {
3400
+ const target = `${datePart.value} 00:00:00`;
3401
+ if (props.canDropExternalEvent?.({
3402
+ dataTransfer: nativeEvent.dataTransfer,
3403
+ start: target
3404
+ }) !== false) emit("externalEventDrop", nativeEvent.dataTransfer, target);
3405
+ else emit("eventPlacementRejected", {
3406
+ action: "external-drop",
3407
+ dataTransfer: nativeEvent.dataTransfer,
3408
+ start: target,
3409
+ conflicts: [],
3410
+ reason: "rejected"
3411
+ });
3412
+ }
3206
3413
  };
3207
3414
  const clickAllDaySlot = (nativeEvent) => emit("allDaySlotClick", date.value, nativeEvent);
3208
3415
  const clickTimeSlot = (slotIndex, nativeEvent) => {
@@ -3223,10 +3430,14 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3223
3430
  startTime: props.startTime,
3224
3431
  endTime: props.endTime
3225
3432
  });
3226
- const handleGridDragOver = (nativeEvent) => slotDropTarget.dragOver(nativeEvent, dropInput());
3433
+ const handleGridDragOver = (nativeEvent) => {
3434
+ dropDataTransfer.value = nativeEvent.dataTransfer;
3435
+ slotDropTarget.dragOver(nativeEvent, dropInput());
3436
+ };
3227
3437
  const handleGridDragLeave = (nativeEvent) => slotDropTarget.dragLeave(nativeEvent, timeSlotsContainer.value);
3228
3438
  const handleGridDrop = (nativeEvent) => {
3229
3439
  const target = slotDropTarget.drop(nativeEvent, dropInput());
3440
+ dropDataTransfer.value = null;
3230
3441
  if (target) emitDrop(nativeEvent, target.target);
3231
3442
  };
3232
3443
  const handleSlotKeydown = (nativeEvent, index) => {
@@ -3450,7 +3661,10 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3450
3661
  event,
3451
3662
  "auto-size": "",
3452
3663
  mode: unref(props).mode,
3453
- mod: { cascade: unref(props).eventOverlapMode === "cascade" },
3664
+ mod: {
3665
+ cascade: unref(props).eventOverlapMode === "cascade",
3666
+ invalid: unref(eventResize).getResizePosition(event.id) !== null && !unref(eventResize).resizeValid.value
3667
+ },
3454
3668
  style: regularEventStyle(event),
3455
3669
  draggable: !isStatic.value && unref(props).withEventsDragAndDrop === true && (unref(props).canDragEvent?.(event) ?? true),
3456
3670
  "with-resize": unref(eventResize).isResizableEvent(event),
@@ -3510,6 +3724,7 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3510
3724
  "hour-start": slot.isHourStart,
3511
3725
  static: isStatic.value,
3512
3726
  "drop-target": unref(slotDropTarget).isTarget(datePart.value, index),
3727
+ invalid: unref(slotDropTarget).isTarget(datePart.value, index) && !dropValid.value,
3513
3728
  "drag-selected": unref(slotDragSelect).isSlotSelected(index, datePart.value),
3514
3729
  "business-hours": businessHoursMods.value[index]["business-hours"],
3515
3730
  "non-business-hours": businessHoursMods.value[index]["non-business-hours"]
@@ -3552,10 +3767,16 @@ var DayView = factory(/* @__PURE__ */ defineComponent({
3552
3767
  });
3553
3768
  //#endregion
3554
3769
  //#region src/components/MobileMonthView/get-mobile-month-view-events.ts
3770
+ function getEventEndDay(event) {
3771
+ const startDay = dayjs(event.start).startOf("day");
3772
+ const end = dayjs(event.end);
3773
+ const endDay = end.hour() === 0 && end.minute() === 0 && end.second() === 0 ? end.startOf("day").subtract(1, "day") : end.startOf("day");
3774
+ return endDay.isBefore(startDay) ? startDay : endDay;
3775
+ }
3555
3776
  function groupEventByDate$1(event, groupedEvents) {
3556
3777
  if (isMultidayEvent(event)) {
3557
3778
  const startDate = dayjs(event.start).startOf("day");
3558
- const endDate = dayjs(event.end).startOf("day");
3779
+ const endDate = getEventEndDay(event);
3559
3780
  for (let date = startDate; date.isBefore(endDate) || date.isSame(endDate); date = date.add(1, "day")) {
3560
3781
  const dateKey = date.format("YYYY-MM-DD");
3561
3782
  if (!groupedEvents[dateKey]) groupedEvents[dateKey] = [];
@@ -3571,9 +3792,11 @@ function getMobileMonthViewEvents({ date, events }) {
3571
3792
  const groupedEvents = {};
3572
3793
  if (events === void 0) return groupedEvents;
3573
3794
  const ids = /* @__PURE__ */ new Set();
3795
+ const monthStart = dayjs(date).startOf("month");
3796
+ const monthEnd = dayjs(date).endOf("month");
3574
3797
  for (const event of events) {
3575
3798
  if (event.display === "background") continue;
3576
- if (dayjs(event.start).isSame(dayjs(date), "month")) {
3799
+ if (!getEventEndDay(event).isBefore(monthStart, "day") && !dayjs(event.start).isAfter(monthEnd, "day")) {
3577
3800
  groupEventByDate$1(validateEvent(event), groupedEvents);
3578
3801
  if (!ids.has(event.id)) ids.add(event.id);
3579
3802
  else throw new Error(`[@mantine/schedule] MobileMonthView: Duplicated event ids found: ${event.id}`);
@@ -3957,17 +4180,6 @@ function calculateEventPositionInWeek({ eventStart, eventEnd, weekStart, weekEnd
3957
4180
  };
3958
4181
  }
3959
4182
  //#endregion
3960
- //#region src/components/MonthView/get-month-view-events/find-available-row.ts
3961
- function findAvailableRow({ existingEvents, startDayIndex, daysSpanned, weekStart }) {
3962
- let row = 0;
3963
- for (const existing of existingEvents) {
3964
- const existingStart = dayjs(existing.start).startOf("day");
3965
- const existingDayIndex = (existingStart.isBefore(weekStart) || existingStart.isSame(weekStart, "day") ? weekStart : existingStart).diff(weekStart, "day");
3966
- if (existingDayIndex + (existing.position?.width || 0) / 100 * 7 > startDayIndex && existingDayIndex < startDayIndex + daysSpanned) row = Math.max(row, (existing.position?.row || 0) + 1);
3967
- }
3968
- return row;
3969
- }
3970
- //#endregion
3971
4183
  //#region src/components/MonthView/get-month-view-events/get-weeks-in-range.ts
3972
4184
  function getWeeksInRange({ rangeStart, rangeEnd, firstDayOfWeek }) {
3973
4185
  const weeks = [];
@@ -3992,6 +4204,14 @@ function getWeeksInRange({ rangeStart, rangeEnd, firstDayOfWeek }) {
3992
4204
  };
3993
4205
  }
3994
4206
  //#endregion
4207
+ //#region src/components/MonthView/get-month-view-events/reserve-row.ts
4208
+ function reserveRow({ nextRowByDay, startDayIndex, daysSpanned }) {
4209
+ const endDayIndex = startDayIndex + daysSpanned;
4210
+ const row = Math.max(...nextRowByDay.slice(startDayIndex, endDayIndex));
4211
+ nextRowByDay.fill(row + 1, startDayIndex, endDayIndex);
4212
+ return row;
4213
+ }
4214
+ //#endregion
3995
4215
  //#region src/components/MonthView/get-month-view-events/get-month-positioned-events.ts
3996
4216
  function getMonthPositionedEvents({ date, events, firstDayOfWeek = 1, range }) {
3997
4217
  const groupedByWeek = {};
@@ -4002,6 +4222,11 @@ function getMonthPositionedEvents({ date, events, firstDayOfWeek = 1, range }) {
4002
4222
  rangeEnd: range ? dayjs(range.end) : dayjs(date).startOf("month").endOf("month"),
4003
4223
  firstDayOfWeek
4004
4224
  });
4225
+ const weekStates = weeks.map((week) => ({
4226
+ weekStart: dayjs(week[0]).startOf("day"),
4227
+ weekEnd: dayjs(week[6]).endOf("day"),
4228
+ nextRowByDay: Array.from({ length: 7 }).fill(0)
4229
+ }));
4005
4230
  for (let i = 0; i < weeks.length; i++) {
4006
4231
  groupedByWeek[i.toString()] = [];
4007
4232
  backgroundByWeek[i.toString()] = [];
@@ -4012,9 +4237,7 @@ function getMonthPositionedEvents({ date, events, firstDayOfWeek = 1, range }) {
4012
4237
  const eventEnd = rawEnd.hour() === 0 && rawEnd.minute() === 0 && rawEnd.second() === 0 ? rawEnd.startOf("day").subtract(1, "day") : rawEnd.startOf("day");
4013
4238
  const isMultiday = eventEnd.isAfter(eventStart);
4014
4239
  for (let weekIdx = 0; weekIdx < weeks.length; weekIdx++) {
4015
- const week = weeks[weekIdx];
4016
- const weekStart = dayjs(week[0]).startOf("day");
4017
- const weekEnd = dayjs(week[6]).endOf("day");
4240
+ const { weekStart, weekEnd, nextRowByDay } = weekStates[weekIdx];
4018
4241
  if ((eventStart.isBefore(weekEnd) || eventStart.isSame(weekEnd, "day")) && (eventEnd.isAfter(weekStart) || eventEnd.isSame(weekStart, "day"))) {
4019
4242
  const { startDayIndex, daysSpanned, startOffset, width, hanging } = calculateEventPositionInWeek({
4020
4243
  eventStart,
@@ -4036,11 +4259,10 @@ function getMonthPositionedEvents({ date, events, firstDayOfWeek = 1, range }) {
4036
4259
  });
4037
4260
  continue;
4038
4261
  }
4039
- const row = findAvailableRow({
4040
- existingEvents: groupedByWeek[weekIdx.toString()],
4262
+ const row = reserveRow({
4263
+ nextRowByDay,
4041
4264
  startDayIndex,
4042
- daysSpanned,
4043
- weekStart
4265
+ daysSpanned
4044
4266
  });
4045
4267
  const positionedEvent = {
4046
4268
  ...event,
@@ -4216,16 +4438,16 @@ function getRenderableMonthEventSegments({ events, groupedByDay, maxEventsPerDay
4216
4438
  });
4217
4439
  }
4218
4440
  var MonthView_module_default = {
4219
- monthView: "_monthView_hbhp2_1",
4220
- monthViewWeekdays: "_monthViewWeekdays_hbhp2_21",
4221
- monthViewWeek: "_monthViewWeek_hbhp2_21",
4222
- monthViewWeekNumber: "_monthViewWeekNumber_hbhp2_31",
4223
- monthViewWeekday: "_monthViewWeekday_hbhp2_21",
4224
- monthViewWeekdaysCorner: "_monthViewWeekdaysCorner_hbhp2_107",
4225
- monthViewDay: "_monthViewDay_hbhp2_114",
4226
- monthViewDayLabel: "_monthViewDayLabel_hbhp2_255",
4227
- monthViewBackgroundEvent: "_monthViewBackgroundEvent_hbhp2_271",
4228
- monthViewEvents: "_monthViewEvents_hbhp2_296"
4441
+ monthView: "_monthView_98v2r_1",
4442
+ monthViewWeekdays: "_monthViewWeekdays_98v2r_21",
4443
+ monthViewWeek: "_monthViewWeek_98v2r_21",
4444
+ monthViewWeekNumber: "_monthViewWeekNumber_98v2r_31",
4445
+ monthViewWeekday: "_monthViewWeekday_98v2r_21",
4446
+ monthViewWeekdaysCorner: "_monthViewWeekdaysCorner_98v2r_107",
4447
+ monthViewDay: "_monthViewDay_98v2r_114",
4448
+ monthViewDayLabel: "_monthViewDayLabel_98v2r_264",
4449
+ monthViewBackgroundEvent: "_monthViewBackgroundEvent_98v2r_280",
4450
+ monthViewEvents: "_monthViewEvents_98v2r_305"
4229
4451
  };
4230
4452
  //#endregion
4231
4453
  //#region src/components/MonthView/MonthView.vue?vue&type=script&setup=true&lang.ts
@@ -4234,6 +4456,7 @@ var _hoisted_1$5 = [
4234
4456
  "data-weekend",
4235
4457
  "data-static",
4236
4458
  "data-drop-target",
4459
+ "data-invalid",
4237
4460
  "data-drag-selected",
4238
4461
  "data-drag-slot-index",
4239
4462
  "data-drag-slot-group",
@@ -4308,6 +4531,9 @@ var MonthView = factory(/* @__PURE__ */ defineComponent({
4308
4531
  type: Function,
4309
4532
  default: void 0
4310
4533
  },
4534
+ canDropEvent: {},
4535
+ canDropExternalEvent: {},
4536
+ preventEventOverlap: { type: [Boolean, Function] },
4311
4537
  withExternalEventDrop: { type: Boolean },
4312
4538
  withDragSlotSelect: { type: Boolean },
4313
4539
  monthYearSelectProps: { default: void 0 },
@@ -4353,6 +4579,7 @@ var MonthView = factory(/* @__PURE__ */ defineComponent({
4353
4579
  "eventDragEnd",
4354
4580
  "externalEventDrop",
4355
4581
  "slotDragEnd",
4582
+ "eventPlacementRejected",
4356
4583
  "dateChange",
4357
4584
  "viewChange",
4358
4585
  "eventClick"
@@ -4393,6 +4620,7 @@ var MonthView = factory(/* @__PURE__ */ defineComponent({
4393
4620
  const eventRenderers = computed(() => resolveEventRenderers(props, slots));
4394
4621
  const monthGrid = ref(null);
4395
4622
  const dropTarget = shallowRef(null);
4623
+ const dropValid = ref(true);
4396
4624
  const isStatic = computed(() => props.mode === "static");
4397
4625
  const month = computed(() => dayjs(props.date).startOf("month"));
4398
4626
  const maxEventsPerDay = computed(() => clampMaxEvents(props.maxEventsPerDay));
@@ -4483,7 +4711,29 @@ var MonthView = factory(/* @__PURE__ */ defineComponent({
4483
4711
  const handleDragOver = (nativeEvent, date) => {
4484
4712
  nativeEvent.preventDefault();
4485
4713
  if (nativeEvent.dataTransfer) nativeEvent.dataTransfer.dropEffect = nativeEvent.dataTransfer.types.includes("application/json") ? "move" : "copy";
4486
- highlightDay(toDateString(date));
4714
+ const target = toDateString(date);
4715
+ const dragged = dragState.draggedEvent.value;
4716
+ if (dragged) {
4717
+ const next = moveEventTo(dragged, target);
4718
+ dropValid.value = isEventPlacementAllowed({
4719
+ event: dragged,
4720
+ start: next.newStart,
4721
+ end: next.newEnd,
4722
+ events: expandedEvents.value,
4723
+ preventEventOverlap: props.preventEventOverlap
4724
+ }).allowed && props.canDropEvent?.({
4725
+ event: dragged,
4726
+ start: next.newStart,
4727
+ end: next.newEnd
4728
+ }) !== false;
4729
+ } else if (nativeEvent.dataTransfer) {
4730
+ const start = `${target} 00:00:00`;
4731
+ dropValid.value = props.canDropExternalEvent?.({
4732
+ dataTransfer: nativeEvent.dataTransfer,
4733
+ start
4734
+ }) !== false;
4735
+ }
4736
+ highlightDay(target);
4487
4737
  };
4488
4738
  const handleDragLeave = (nativeEvent) => {
4489
4739
  if (!(nativeEvent.relatedTarget instanceof Node) || !monthGrid.value?.contains(nativeEvent.relatedTarget)) {
@@ -4495,14 +4745,48 @@ var MonthView = factory(/* @__PURE__ */ defineComponent({
4495
4745
  nativeEvent.preventDefault();
4496
4746
  highlightDay.cancel();
4497
4747
  setDropTarget(null);
4748
+ dropValid.value = true;
4498
4749
  const event = getDropEvent(expandedEvents.value, nativeEvent.dataTransfer);
4499
4750
  if (event) {
4500
4751
  const { start } = calculateMonthDropDate({
4501
4752
  draggedEvent: event,
4502
4753
  targetDay: toDateString(date)
4503
4754
  });
4504
- emit("eventDrop", moveEventTo(event, start));
4505
- } else if (nativeEvent.dataTransfer) emit("externalEventDrop", nativeEvent.dataTransfer, toDateString(date));
4755
+ const next = moveEventTo(event, start);
4756
+ const validation = isEventPlacementAllowed({
4757
+ event,
4758
+ start: next.newStart,
4759
+ end: next.newEnd,
4760
+ events: expandedEvents.value,
4761
+ preventEventOverlap: props.preventEventOverlap
4762
+ });
4763
+ if (validation.allowed && props.canDropEvent?.({
4764
+ event,
4765
+ start: next.newStart,
4766
+ end: next.newEnd
4767
+ }) !== false) emit("eventDrop", next);
4768
+ else emit("eventPlacementRejected", {
4769
+ action: "drop",
4770
+ event,
4771
+ start: next.newStart,
4772
+ end: next.newEnd,
4773
+ conflicts: validation.conflicts,
4774
+ reason: validation.allowed ? "rejected" : "overlap"
4775
+ });
4776
+ } else if (nativeEvent.dataTransfer) {
4777
+ const start = `${toDateString(date)} 00:00:00`;
4778
+ if (props.canDropExternalEvent?.({
4779
+ dataTransfer: nativeEvent.dataTransfer,
4780
+ start
4781
+ }) !== false) emit("externalEventDrop", nativeEvent.dataTransfer, toDateString(date));
4782
+ else emit("eventPlacementRejected", {
4783
+ action: "external-drop",
4784
+ dataTransfer: nativeEvent.dataTransfer,
4785
+ start,
4786
+ conflicts: [],
4787
+ reason: "rejected"
4788
+ });
4789
+ }
4506
4790
  };
4507
4791
  const segmentStyle = (position) => ({
4508
4792
  position: "absolute",
@@ -4576,6 +4860,7 @@ var MonthView = factory(/* @__PURE__ */ defineComponent({
4576
4860
  "data-weekend": unref(props).weekendDays.includes(unref(dayjs)(date).day()) || void 0,
4577
4861
  "data-static": isStatic.value || void 0,
4578
4862
  "data-drop-target": dropTarget.value === unref(toDateString)(date) || void 0,
4863
+ "data-invalid": dropTarget.value === unref(toDateString)(date) && !dropValid.value || void 0,
4579
4864
  "data-drag-selected": unref(slotDragSelect).isSlotSelected(weekIndex * 7 + dayIndex, "month") || void 0,
4580
4865
  "data-drag-slot-index": withSlotSelect.value ? weekIndex * 7 + dayIndex : void 0,
4581
4866
  "data-drag-slot-group": withSlotSelect.value ? MONTH_SLOT_GROUP : void 0,
@@ -5022,29 +5307,29 @@ function getWeekViewEvents(input) {
5022
5307
  });
5023
5308
  }
5024
5309
  var WeekView_module_default = {
5025
- weekView: "_weekView_jkexi_1",
5026
- weekViewRoot: "_weekViewRoot_jkexi_22",
5027
- weekViewDragPreview: "_weekViewDragPreview_jkexi_33",
5028
- weekViewInner: "_weekViewInner_jkexi_39",
5029
- weekViewScrollArea: "_weekViewScrollArea_jkexi_45",
5030
- weekViewHeader: "_weekViewHeader_jkexi_51",
5031
- weekViewCorner: "_weekViewCorner_jkexi_66",
5032
- weekViewSlotLabels: "_weekViewSlotLabels_jkexi_77",
5033
- weekViewSlotLabel: "_weekViewSlotLabel_jkexi_77",
5034
- weekViewDay: "_weekViewDay_jkexi_104",
5035
- weekViewDayLabel: "_weekViewDayLabel_jkexi_109",
5036
- weekViewDayNumber: "_weekViewDayNumber_jkexi_147",
5037
- weekViewDayWeekday: "_weekViewDayWeekday_jkexi_163",
5038
- weekViewBackgroundEvent: "_weekViewBackgroundEvent_jkexi_169",
5039
- weekViewBackgroundEventResizeHandle: "_weekViewBackgroundEventResizeHandle_jkexi_198",
5040
- weekViewDaySlots: "_weekViewDaySlots_jkexi_246",
5041
- weekViewDaySlot: "_weekViewDaySlot_jkexi_246",
5042
- weekViewWeekLabel: "_weekViewWeekLabel_jkexi_344",
5043
- weekViewWeekNumber: "_weekViewWeekNumber_jkexi_350",
5044
- weekViewAllDaySlots: "_weekViewAllDaySlots_jkexi_356",
5045
- weekViewAllDaySlotsLabel: "_weekViewAllDaySlotsLabel_jkexi_361",
5046
- weekViewAllDaySlotsEvents: "_weekViewAllDaySlotsEvents_jkexi_368",
5047
- weekViewAllDaySlotsList: "_weekViewAllDaySlotsList_jkexi_375"
5310
+ weekView: "_weekView_1ttnb_1",
5311
+ weekViewRoot: "_weekViewRoot_1ttnb_22",
5312
+ weekViewDragPreview: "_weekViewDragPreview_1ttnb_33",
5313
+ weekViewInner: "_weekViewInner_1ttnb_39",
5314
+ weekViewScrollArea: "_weekViewScrollArea_1ttnb_45",
5315
+ weekViewHeader: "_weekViewHeader_1ttnb_51",
5316
+ weekViewCorner: "_weekViewCorner_1ttnb_66",
5317
+ weekViewSlotLabels: "_weekViewSlotLabels_1ttnb_77",
5318
+ weekViewSlotLabel: "_weekViewSlotLabel_1ttnb_77",
5319
+ weekViewDay: "_weekViewDay_1ttnb_104",
5320
+ weekViewDayLabel: "_weekViewDayLabel_1ttnb_109",
5321
+ weekViewDayNumber: "_weekViewDayNumber_1ttnb_147",
5322
+ weekViewDayWeekday: "_weekViewDayWeekday_1ttnb_163",
5323
+ weekViewBackgroundEvent: "_weekViewBackgroundEvent_1ttnb_169",
5324
+ weekViewBackgroundEventResizeHandle: "_weekViewBackgroundEventResizeHandle_1ttnb_198",
5325
+ weekViewDaySlots: "_weekViewDaySlots_1ttnb_246",
5326
+ weekViewDaySlot: "_weekViewDaySlot_1ttnb_246",
5327
+ weekViewWeekLabel: "_weekViewWeekLabel_1ttnb_353",
5328
+ weekViewWeekNumber: "_weekViewWeekNumber_1ttnb_359",
5329
+ weekViewAllDaySlots: "_weekViewAllDaySlots_1ttnb_365",
5330
+ weekViewAllDaySlotsLabel: "_weekViewAllDaySlotsLabel_1ttnb_370",
5331
+ weekViewAllDaySlotsEvents: "_weekViewAllDaySlotsEvents_1ttnb_377",
5332
+ weekViewAllDaySlotsList: "_weekViewAllDaySlotsList_1ttnb_384"
5048
5333
  };
5049
5334
  //#endregion
5050
5335
  //#region src/components/WeekView/WeekView.vue?vue&type=script&setup=true&lang.ts
@@ -5160,6 +5445,9 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5160
5445
  type: Function,
5161
5446
  default: void 0
5162
5447
  },
5448
+ canDropEvent: {},
5449
+ canDropExternalEvent: {},
5450
+ preventEventOverlap: { type: [Boolean, Function] },
5163
5451
  withDragSlotSelect: { type: Boolean },
5164
5452
  withExternalEventDrop: { type: Boolean },
5165
5453
  startScrollTime: { default: void 0 },
@@ -5168,6 +5456,7 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5168
5456
  type: Function,
5169
5457
  default: void 0
5170
5458
  },
5459
+ canResizeEventTo: {},
5171
5460
  date: {},
5172
5461
  events: { default: void 0 },
5173
5462
  locale: { default: void 0 },
@@ -5209,6 +5498,7 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5209
5498
  "slotDragEnd",
5210
5499
  "externalEventDrop",
5211
5500
  "eventResize",
5501
+ "eventPlacementRejected",
5212
5502
  "dateChange",
5213
5503
  "viewChange",
5214
5504
  "eventClick"
@@ -5253,6 +5543,7 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5253
5543
  };
5254
5544
  const daySlotsContainers = /* @__PURE__ */ new Map();
5255
5545
  const slotDropTarget = useSlotDropTarget();
5546
+ const dropDataTransfer = shallowRef(null);
5256
5547
  const isStatic = computed(() => props.mode === "static");
5257
5548
  /** The plural names are the deprecated aliases; the canonical prop wins when both are set. */
5258
5549
  const withWeekNumber = computed(() => props.withWeekNumbers ?? props.withWeekNumber);
@@ -5344,6 +5635,10 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5344
5635
  resizeIntervalMinutes: () => props.eventResizeInterval,
5345
5636
  onEventResize: (data) => emit("eventResize", data),
5346
5637
  canResizeEvent: () => props.canResizeEvent,
5638
+ events: () => expandedEvents.value,
5639
+ preventEventOverlap: () => props.preventEventOverlap,
5640
+ canResizeEventTo: () => props.canResizeEventTo,
5641
+ onEventPlacementRejected: (data) => emit("eventPlacementRejected", data),
5347
5642
  withBackgroundEvents: () => Boolean(props.withInteractiveBackgroundEvents)
5348
5643
  });
5349
5644
  const slotDragSelect = useSlotDragSelect({
@@ -5375,9 +5670,35 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5375
5670
  isSlotDragging: () => slotDragSelect.isDragging(),
5376
5671
  onDragEnd: () => {
5377
5672
  slotDropTarget.reset();
5673
+ dropDataTransfer.value = null;
5378
5674
  emit("eventDragEnd");
5379
5675
  }
5380
5676
  });
5677
+ const dropValid = computed(() => {
5678
+ const target = slotDropTarget.dropTarget.value;
5679
+ const interval = target && intervals.value[target.slotIndex];
5680
+ if (!target || !interval) return true;
5681
+ const start = `${target.date} ${interval.startTime}`;
5682
+ const event = dragState.draggedEvent.value;
5683
+ if (event) {
5684
+ const next = moveEventTo(event, start);
5685
+ return isEventPlacementAllowed({
5686
+ event,
5687
+ start: next.newStart,
5688
+ end: next.newEnd,
5689
+ events: expandedEvents.value,
5690
+ preventEventOverlap: props.preventEventOverlap
5691
+ }).allowed && props.canDropEvent?.({
5692
+ event,
5693
+ start: next.newStart,
5694
+ end: next.newEnd
5695
+ }) !== false;
5696
+ }
5697
+ return dropDataTransfer.value ? props.canDropExternalEvent?.({
5698
+ dataTransfer: dropDataTransfer.value,
5699
+ start
5700
+ }) !== false : true;
5701
+ });
5381
5702
  const clickEvent = (event, nativeEvent) => emit("eventClick", event, nativeEvent);
5382
5703
  const dragStart = (event) => {
5383
5704
  dragState.startEventDrag(event);
@@ -5431,15 +5752,80 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5431
5752
  const emitDrop = (nativeEvent, target) => {
5432
5753
  nativeEvent.preventDefault();
5433
5754
  const event = getDropEvent(expandedEvents.value, nativeEvent.dataTransfer);
5434
- if (event) emit("eventDrop", moveEventTo(event, target));
5435
- else if (nativeEvent.dataTransfer) emit("externalEventDrop", nativeEvent.dataTransfer, target);
5755
+ if (event) {
5756
+ const next = moveEventTo(event, target);
5757
+ const validation = isEventPlacementAllowed({
5758
+ event,
5759
+ start: next.newStart,
5760
+ end: next.newEnd,
5761
+ events: expandedEvents.value,
5762
+ preventEventOverlap: props.preventEventOverlap
5763
+ });
5764
+ if (validation.allowed && props.canDropEvent?.({
5765
+ event,
5766
+ start: next.newStart,
5767
+ end: next.newEnd
5768
+ }) !== false) emit("eventDrop", next);
5769
+ else emit("eventPlacementRejected", {
5770
+ action: "drop",
5771
+ event,
5772
+ start: next.newStart,
5773
+ end: next.newEnd,
5774
+ conflicts: validation.conflicts,
5775
+ reason: validation.allowed ? "rejected" : "overlap"
5776
+ });
5777
+ } else if (nativeEvent.dataTransfer) if (props.canDropExternalEvent?.({
5778
+ dataTransfer: nativeEvent.dataTransfer,
5779
+ start: target
5780
+ }) !== false) emit("externalEventDrop", nativeEvent.dataTransfer, target);
5781
+ else emit("eventPlacementRejected", {
5782
+ action: "external-drop",
5783
+ dataTransfer: nativeEvent.dataTransfer,
5784
+ start: target,
5785
+ conflicts: [],
5786
+ reason: "rejected"
5787
+ });
5436
5788
  };
5437
5789
  const emitAllDayDrop = (nativeEvent, date) => {
5438
5790
  nativeEvent.preventDefault();
5439
5791
  const dayKey = dayjs(date).format("YYYY-MM-DD");
5440
5792
  const event = getDropEvent(expandedEvents.value, nativeEvent.dataTransfer);
5441
- if (event) emit("eventDrop", moveEventToAllDay(event, dayKey));
5442
- else if (nativeEvent.dataTransfer) emit("externalEventDrop", nativeEvent.dataTransfer, `${dayKey} 00:00:00`);
5793
+ if (event) {
5794
+ const next = moveEventToAllDay(event, dayKey);
5795
+ const validation = isEventPlacementAllowed({
5796
+ event,
5797
+ start: next.newStart,
5798
+ end: next.newEnd,
5799
+ events: expandedEvents.value,
5800
+ preventEventOverlap: props.preventEventOverlap
5801
+ });
5802
+ if (validation.allowed && props.canDropEvent?.({
5803
+ event,
5804
+ start: next.newStart,
5805
+ end: next.newEnd
5806
+ }) !== false) emit("eventDrop", next);
5807
+ else emit("eventPlacementRejected", {
5808
+ action: "drop",
5809
+ event,
5810
+ start: next.newStart,
5811
+ end: next.newEnd,
5812
+ conflicts: validation.conflicts,
5813
+ reason: validation.allowed ? "rejected" : "overlap"
5814
+ });
5815
+ } else if (nativeEvent.dataTransfer) {
5816
+ const target = `${dayKey} 00:00:00`;
5817
+ if (props.canDropExternalEvent?.({
5818
+ dataTransfer: nativeEvent.dataTransfer,
5819
+ start: target
5820
+ }) !== false) emit("externalEventDrop", nativeEvent.dataTransfer, target);
5821
+ else emit("eventPlacementRejected", {
5822
+ action: "external-drop",
5823
+ dataTransfer: nativeEvent.dataTransfer,
5824
+ start: target,
5825
+ conflicts: [],
5826
+ reason: "rejected"
5827
+ });
5828
+ }
5443
5829
  };
5444
5830
  const dropInput = (date) => ({
5445
5831
  container: daySlotsContainers.get(date),
@@ -5450,10 +5836,14 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5450
5836
  startTime: props.startTime,
5451
5837
  endTime: props.endTime
5452
5838
  });
5453
- const handleDayDragOver = (nativeEvent, date) => slotDropTarget.dragOver(nativeEvent, dropInput(date));
5839
+ const handleDayDragOver = (nativeEvent, date) => {
5840
+ dropDataTransfer.value = nativeEvent.dataTransfer;
5841
+ slotDropTarget.dragOver(nativeEvent, dropInput(date));
5842
+ };
5454
5843
  const handleDayDragLeave = (nativeEvent, date) => slotDropTarget.dragLeave(nativeEvent, daySlotsContainers.get(date));
5455
5844
  const handleDayDrop = (nativeEvent, date) => {
5456
5845
  const target = slotDropTarget.drop(nativeEvent, dropInput(date));
5846
+ dropDataTransfer.value = null;
5457
5847
  if (target) emitDrop(nativeEvent, target.target);
5458
5848
  };
5459
5849
  const allDayEventStyle = (position) => ({
@@ -5664,6 +6054,7 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5664
6054
  "data-drag-slot-index": withSlotSelect.value ? slotIndex : void 0,
5665
6055
  "data-drag-slot-group": withSlotSelect.value ? column.key : void 0,
5666
6056
  "data-drop-target": unref(slotDropTarget).isTarget(column.key, slotIndex) || void 0,
6057
+ "data-invalid": unref(slotDropTarget).isTarget(column.key, slotIndex) && !dropValid.value ? true : void 0,
5667
6058
  "data-drag-selected": unref(slotDragSelect).isSlotSelected(slotIndex, column.key) || void 0,
5668
6059
  "data-business-hours": businessHoursMods.value[dayIndex][slotIndex]["business-hours"] || void 0,
5669
6060
  "data-non-business-hours": businessHoursMods.value[dayIndex][slotIndex]["non-business-hours"] || void 0,
@@ -5680,6 +6071,7 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5680
6071
  "data-drag-slot-index",
5681
6072
  "data-drag-slot-group",
5682
6073
  "data-drop-target",
6074
+ "data-invalid",
5683
6075
  "data-drag-selected",
5684
6076
  "data-business-hours",
5685
6077
  "data-non-business-hours",
@@ -5722,7 +6114,10 @@ var WeekView = factory(/* @__PURE__ */ defineComponent({
5722
6114
  event,
5723
6115
  "auto-size": "",
5724
6116
  mode: unref(props).mode,
5725
- mod: { cascade: unref(props).eventOverlapMode === "cascade" },
6117
+ mod: {
6118
+ cascade: unref(props).eventOverlapMode === "cascade",
6119
+ invalid: unref(eventResize).getResizePosition(event.id) !== null && !unref(eventResize).resizeValid.value
6120
+ },
5726
6121
  style: regularEventStyle(event),
5727
6122
  draggable: isDraggableEvent(event),
5728
6123
  "with-resize": unref(eventResize).isResizableEvent(event),
@@ -6181,6 +6576,22 @@ var Schedule = factory(/* @__PURE__ */ defineComponent({
6181
6576
  type: Function,
6182
6577
  default: void 0
6183
6578
  },
6579
+ canDropEvent: {
6580
+ type: Function,
6581
+ default: void 0
6582
+ },
6583
+ canDropExternalEvent: {
6584
+ type: Function,
6585
+ default: void 0
6586
+ },
6587
+ canResizeEventTo: {
6588
+ type: Function,
6589
+ default: void 0
6590
+ },
6591
+ preventEventOverlap: {
6592
+ type: [Boolean, Function],
6593
+ default: void 0
6594
+ },
6184
6595
  withInteractiveBackgroundEvents: {
6185
6596
  type: Boolean,
6186
6597
  default: void 0
@@ -6212,7 +6623,8 @@ var Schedule = factory(/* @__PURE__ */ defineComponent({
6212
6623
  "monthClick",
6213
6624
  "slotDragEnd",
6214
6625
  "externalEventDrop",
6215
- "eventResize"
6626
+ "eventResize",
6627
+ "eventPlacementRejected"
6216
6628
  ],
6217
6629
  setup(__props, { emit: __emit }) {
6218
6630
  const rawProps = __props;
@@ -6271,6 +6683,10 @@ var Schedule = factory(/* @__PURE__ */ defineComponent({
6271
6683
  withExternalEventDrop: props.withExternalEventDrop,
6272
6684
  withEventResize: props.withEventResize,
6273
6685
  canResizeEvent: props.canResizeEvent,
6686
+ canDropEvent: props.canDropEvent,
6687
+ canDropExternalEvent: props.canDropExternalEvent,
6688
+ canResizeEventTo: props.canResizeEventTo,
6689
+ preventEventOverlap: props.preventEventOverlap,
6274
6690
  withInteractiveBackgroundEvents: props.mode === "static" ? false : props.withInteractiveBackgroundEvents,
6275
6691
  recurrenceExpansionLimit: props.recurrenceExpansionLimit,
6276
6692
  ...eventRenderers.value,
@@ -6294,7 +6710,8 @@ var Schedule = factory(/* @__PURE__ */ defineComponent({
6294
6710
  onMonthClick: (month) => emit("monthClick", month),
6295
6711
  onSlotDragEnd: (rangeStart, rangeEnd) => emit("slotDragEnd", rangeStart, rangeEnd),
6296
6712
  onExternalEventDrop: (dataTransfer, dateTime) => emit("externalEventDrop", dataTransfer, dateTime),
6297
- onEventResize: (data) => emit("eventResize", data)
6713
+ onEventResize: (data) => emit("eventResize", data),
6714
+ onEventPlacementRejected: (data) => emit("eventPlacementRejected", data)
6298
6715
  };
6299
6716
  const views = {
6300
6717
  day: DayView,
@@ -6364,6 +6781,7 @@ var Schedule = factory(/* @__PURE__ */ defineComponent({
6364
6781
  //#region src/hooks/use-horizontal-event-resize.ts
6365
6782
  function useHorizontalEventResize(input) {
6366
6783
  const state = shallowRef(null);
6784
+ const resizeValid = ref(true);
6367
6785
  let justResized = false;
6368
6786
  let savedUserSelect = "";
6369
6787
  const metrics = () => {
@@ -6408,6 +6826,18 @@ function useHorizontalEventResize(input) {
6408
6826
  current.currentWidth = right - current.currentLeft;
6409
6827
  }
6410
6828
  state.value = { ...current };
6829
+ const start = current.edge === "start" ? toDateTime(current.currentLeft, current.eventDate) : current.originalStart;
6830
+ const end = current.edge === "end" ? toDateTime(current.currentLeft + current.currentWidth, current.eventDate) : current.originalEnd;
6831
+ resizeValid.value = validateEventResize({
6832
+ event: current.event,
6833
+ start,
6834
+ end,
6835
+ edge: current.edge,
6836
+ events: input.events?.() ?? [],
6837
+ preventEventOverlap: input.preventEventOverlap?.(),
6838
+ canResizeEventTo: input.canResizeEventTo?.(),
6839
+ resourceId: current.event.resourceId
6840
+ }).valid;
6411
6841
  });
6412
6842
  const trackPointer = (event) => move(event.clientX);
6413
6843
  const cleanup = () => {
@@ -6419,13 +6849,37 @@ function useHorizontalEventResize(input) {
6419
6849
  const finish = () => {
6420
6850
  move.cancel();
6421
6851
  const current = state.value;
6422
- if (current && (current.currentLeft !== current.originalLeft || current.currentWidth !== current.originalWidth)) input.onEventResize({
6423
- eventId: current.event.id,
6424
- newStart: current.edge === "start" ? toDateTime(current.currentLeft, current.eventDate) : current.originalStart,
6425
- newEnd: current.edge === "end" ? toDateTime(current.currentLeft + current.currentWidth, current.eventDate) : current.originalEnd,
6426
- event: current.event
6427
- });
6852
+ if (current && (current.currentLeft !== current.originalLeft || current.currentWidth !== current.originalWidth)) {
6853
+ const start = current.edge === "start" ? toDateTime(current.currentLeft, current.eventDate) : current.originalStart;
6854
+ const end = current.edge === "end" ? toDateTime(current.currentLeft + current.currentWidth, current.eventDate) : current.originalEnd;
6855
+ const validation = validateEventResize({
6856
+ event: current.event,
6857
+ start,
6858
+ end,
6859
+ edge: current.edge,
6860
+ events: input.events?.() ?? [],
6861
+ preventEventOverlap: input.preventEventOverlap?.(),
6862
+ canResizeEventTo: input.canResizeEventTo?.(),
6863
+ resourceId: current.event.resourceId
6864
+ });
6865
+ if (validation.valid) input.onEventResize({
6866
+ eventId: current.event.id,
6867
+ newStart: start,
6868
+ newEnd: end,
6869
+ event: current.event
6870
+ });
6871
+ else input.onEventPlacementRejected?.({
6872
+ action: "resize",
6873
+ event: current.event,
6874
+ start,
6875
+ end,
6876
+ edge: current.edge,
6877
+ conflicts: validation.conflicts,
6878
+ reason: validation.reason
6879
+ });
6880
+ }
6428
6881
  state.value = null;
6882
+ resizeValid.value = true;
6429
6883
  cleanup();
6430
6884
  justResized = true;
6431
6885
  requestAnimationFrame(() => justResized = false);
@@ -6443,6 +6897,7 @@ function useHorizontalEventResize(input) {
6443
6897
  dayIndex: params.dayIndex ?? 0,
6444
6898
  dayCount: params.dayCount ?? 1
6445
6899
  };
6900
+ resizeValid.value = true;
6446
6901
  savedUserSelect = document.body.style.userSelect;
6447
6902
  document.body.style.userSelect = "none";
6448
6903
  document.addEventListener("pointermove", trackPointer);
@@ -6451,6 +6906,7 @@ function useHorizontalEventResize(input) {
6451
6906
  onBeforeUnmount(cleanup);
6452
6907
  return {
6453
6908
  state,
6909
+ resizeValid,
6454
6910
  get resizingEdge() {
6455
6911
  return state.value?.edge ?? null;
6456
6912
  },
@@ -6561,27 +7017,27 @@ function getResourcesDayViewEvents({ events, resources, date, startTime, endTime
6561
7017
  return result;
6562
7018
  }
6563
7019
  var ResourcesDayView_module_default = {
6564
- resourcesDayView: "_resourcesDayView_bsrxh_1",
6565
- resourcesDayViewRoot: "_resourcesDayViewRoot_bsrxh_22",
6566
- resourcesDayViewScrollArea: "_resourcesDayViewScrollArea_bsrxh_30",
6567
- resourcesDayViewInner: "_resourcesDayViewInner_bsrxh_39",
6568
- resourcesDayViewTimeLabelsRow: "_resourcesDayViewTimeLabelsRow_bsrxh_44",
6569
- resourcesDayViewCorner: "_resourcesDayViewCorner_bsrxh_57",
6570
- resourcesDayViewTimeLabel: "_resourcesDayViewTimeLabel_bsrxh_44",
6571
- resourcesDayViewRow: "_resourcesDayViewRow_bsrxh_96",
6572
- resourcesDayViewResourceLabel: "_resourcesDayViewResourceLabel_bsrxh_100",
6573
- resourcesDayViewGroupColumn: "_resourcesDayViewGroupColumn_bsrxh_124",
6574
- resourcesDayViewGroupColumnEmpty: "_resourcesDayViewGroupColumnEmpty_bsrxh_125",
6575
- resourcesDayViewRowSlots: "_resourcesDayViewRowSlots_bsrxh_153",
6576
- resourcesDayViewRowSlot: "_resourcesDayViewRowSlot_bsrxh_153",
6577
- resourcesDayViewCurrentTimeIndicator: "_resourcesDayViewCurrentTimeIndicator_bsrxh_231",
6578
- resourcesDayViewCurrentTimeIndicatorLine: "_resourcesDayViewCurrentTimeIndicatorLine_bsrxh_243",
6579
- resourcesDayViewCurrentTimeIndicatorThumb: "_resourcesDayViewCurrentTimeIndicatorThumb_bsrxh_249",
6580
- resourcesDayViewCurrentTimeIndicatorTimeBubble: "_resourcesDayViewCurrentTimeIndicatorTimeBubble_bsrxh_259",
6581
- resourcesDayViewBackgroundEvent: "_resourcesDayViewBackgroundEvent_bsrxh_278",
6582
- resourcesDayViewAllDayEvent: "_resourcesDayViewAllDayEvent_bsrxh_306",
6583
- resourcesDayViewEventWrapper: "_resourcesDayViewEventWrapper_bsrxh_312",
6584
- resourcesDayViewResizeHandle: "_resourcesDayViewResizeHandle_bsrxh_316"
7020
+ resourcesDayView: "_resourcesDayView_1ak2d_1",
7021
+ resourcesDayViewRoot: "_resourcesDayViewRoot_1ak2d_22",
7022
+ resourcesDayViewScrollArea: "_resourcesDayViewScrollArea_1ak2d_30",
7023
+ resourcesDayViewInner: "_resourcesDayViewInner_1ak2d_39",
7024
+ resourcesDayViewTimeLabelsRow: "_resourcesDayViewTimeLabelsRow_1ak2d_44",
7025
+ resourcesDayViewCorner: "_resourcesDayViewCorner_1ak2d_57",
7026
+ resourcesDayViewTimeLabel: "_resourcesDayViewTimeLabel_1ak2d_44",
7027
+ resourcesDayViewRow: "_resourcesDayViewRow_1ak2d_96",
7028
+ resourcesDayViewResourceLabel: "_resourcesDayViewResourceLabel_1ak2d_100",
7029
+ resourcesDayViewGroupColumn: "_resourcesDayViewGroupColumn_1ak2d_124",
7030
+ resourcesDayViewGroupColumnEmpty: "_resourcesDayViewGroupColumnEmpty_1ak2d_125",
7031
+ resourcesDayViewRowSlots: "_resourcesDayViewRowSlots_1ak2d_153",
7032
+ resourcesDayViewRowSlot: "_resourcesDayViewRowSlot_1ak2d_153",
7033
+ resourcesDayViewCurrentTimeIndicator: "_resourcesDayViewCurrentTimeIndicator_1ak2d_240",
7034
+ resourcesDayViewCurrentTimeIndicatorLine: "_resourcesDayViewCurrentTimeIndicatorLine_1ak2d_252",
7035
+ resourcesDayViewCurrentTimeIndicatorThumb: "_resourcesDayViewCurrentTimeIndicatorThumb_1ak2d_258",
7036
+ resourcesDayViewCurrentTimeIndicatorTimeBubble: "_resourcesDayViewCurrentTimeIndicatorTimeBubble_1ak2d_268",
7037
+ resourcesDayViewBackgroundEvent: "_resourcesDayViewBackgroundEvent_1ak2d_287",
7038
+ resourcesDayViewAllDayEvent: "_resourcesDayViewAllDayEvent_1ak2d_315",
7039
+ resourcesDayViewEventWrapper: "_resourcesDayViewEventWrapper_1ak2d_321",
7040
+ resourcesDayViewResizeHandle: "_resourcesDayViewResizeHandle_1ak2d_325"
6585
7041
  };
6586
7042
  //#endregion
6587
7043
  //#region src/components/ResourcesDayView/ResourcesDayView.vue?vue&type=script&setup=true&lang.ts
@@ -6706,6 +7162,10 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
6706
7162
  type: Function,
6707
7163
  default: void 0
6708
7164
  },
7165
+ canDropEvent: {},
7166
+ canDropExternalEvent: {},
7167
+ canResizeEventTo: {},
7168
+ preventEventOverlap: { type: [Boolean, Function] },
6709
7169
  recurrenceExpansionLimit: { default: void 0 },
6710
7170
  maxEventsPerTimeSlot: { default: void 0 },
6711
7171
  moreEventsProps: { default: void 0 },
@@ -6724,7 +7184,8 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
6724
7184
  "timeSlotClick",
6725
7185
  "slotDragEnd",
6726
7186
  "externalEventDrop",
6727
- "eventResize"
7187
+ "eventResize",
7188
+ "eventPlacementRejected"
6728
7189
  ],
6729
7190
  setup(__props, { emit: __emit }) {
6730
7191
  const rawProps = __props;
@@ -6768,6 +7229,7 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
6768
7229
  rootElement.value = node instanceof HTMLElement ? node : null;
6769
7230
  };
6770
7231
  const dropTarget = shallowRef(null);
7232
+ const dropValid = ref(true);
6771
7233
  const scrolled = ref(false);
6772
7234
  const scrolledX = ref(false);
6773
7235
  const isStatic = computed(() => props.mode === "static");
@@ -6844,6 +7306,10 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
6844
7306
  resizeIntervalMinutes: () => props.eventResizeInterval,
6845
7307
  onEventResize: (data) => emit("eventResize", data),
6846
7308
  canResizeEvent: () => props.canResizeEvent,
7309
+ events: () => expandedEvents.value,
7310
+ preventEventOverlap: () => props.preventEventOverlap,
7311
+ canResizeEventTo: () => props.canResizeEventTo,
7312
+ onEventPlacementRejected: (data) => emit("eventPlacementRejected", data),
6847
7313
  withBackgroundEvents: () => Boolean(props.withInteractiveBackgroundEvents)
6848
7314
  });
6849
7315
  onMounted(async () => {
@@ -6877,15 +7343,51 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
6877
7343
  if (!intervals.value[slotIndex]) return;
6878
7344
  const target = getSnappedDropTarget(nativeEvent, slotIndex);
6879
7345
  const event = getDropEvent(expandedEvents.value, nativeEvent.dataTransfer);
6880
- if (event) emit("eventDrop", {
6881
- ...moveEventTo(event, target),
7346
+ if (event) {
7347
+ const next = moveEventTo(event, target);
7348
+ const validation = isEventPlacementAllowed({
7349
+ event,
7350
+ start: next.newStart,
7351
+ end: next.newEnd,
7352
+ events: expandedEvents.value,
7353
+ preventEventOverlap: props.preventEventOverlap,
7354
+ resourceId
7355
+ });
7356
+ if (validation.allowed && props.canDropEvent?.({
7357
+ event,
7358
+ start: next.newStart,
7359
+ end: next.newEnd,
7360
+ resourceId
7361
+ }) !== false) emit("eventDrop", {
7362
+ ...next,
7363
+ resourceId
7364
+ });
7365
+ else emit("eventPlacementRejected", {
7366
+ action: "drop",
7367
+ event,
7368
+ start: next.newStart,
7369
+ end: next.newEnd,
7370
+ resourceId,
7371
+ conflicts: validation.conflicts,
7372
+ reason: validation.allowed ? "rejected" : "overlap"
7373
+ });
7374
+ } else if (nativeEvent.dataTransfer) if (props.canDropExternalEvent?.({
7375
+ dataTransfer: nativeEvent.dataTransfer,
7376
+ start: target,
6882
7377
  resourceId
6883
- });
6884
- else if (nativeEvent.dataTransfer) emit("externalEventDrop", {
7378
+ }) !== false) emit("externalEventDrop", {
6885
7379
  dataTransfer: nativeEvent.dataTransfer,
6886
7380
  dropDateTime: target,
6887
7381
  resourceId
6888
7382
  });
7383
+ else emit("eventPlacementRejected", {
7384
+ action: "external-drop",
7385
+ dataTransfer: nativeEvent.dataTransfer,
7386
+ start: target,
7387
+ resourceId,
7388
+ conflicts: [],
7389
+ reason: "rejected"
7390
+ });
6889
7391
  };
6890
7392
  const getSnappedDropTarget = (nativeEvent, slotIndex) => {
6891
7393
  const interval = intervals.value[slotIndex];
@@ -6916,6 +7418,28 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
6916
7418
  */
6917
7419
  const resolveDropTarget = rafThrottle((nativeEvent, resourceId, resourceIndex) => {
6918
7420
  const slotIndex = getSlotIndexAtPoint(nativeEvent, resourceIndex);
7421
+ const target = slotIndex < 0 ? null : getSnappedDropTarget(nativeEvent, slotIndex);
7422
+ const event = dragState.draggedEvent.value;
7423
+ if (target && event) {
7424
+ const next = moveEventTo(event, target);
7425
+ dropValid.value = isEventPlacementAllowed({
7426
+ event,
7427
+ start: next.newStart,
7428
+ end: next.newEnd,
7429
+ events: expandedEvents.value,
7430
+ preventEventOverlap: props.preventEventOverlap,
7431
+ resourceId
7432
+ }).allowed && props.canDropEvent?.({
7433
+ event,
7434
+ start: next.newStart,
7435
+ end: next.newEnd,
7436
+ resourceId
7437
+ }) !== false;
7438
+ } else if (target && nativeEvent.dataTransfer) dropValid.value = props.canDropExternalEvent?.({
7439
+ dataTransfer: nativeEvent.dataTransfer,
7440
+ start: target,
7441
+ resourceId
7442
+ }) !== false;
6919
7443
  setDropTarget(slotIndex < 0 ? null : {
6920
7444
  resourceId,
6921
7445
  slotIndex
@@ -7229,7 +7753,8 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
7229
7753
  style: {
7230
7754
  width: "100%",
7231
7755
  height: "100%"
7232
- }
7756
+ },
7757
+ mod: { invalid: unref(resize).getResizePosition(event.id) !== null && !unref(resize).resizeValid.value }
7233
7758
  }, { ref_for: true }, {
7234
7759
  ...eventRenderers.value,
7235
7760
  ...stylesApi.value
@@ -7242,6 +7767,7 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
7242
7767
  "radius",
7243
7768
  "mode",
7244
7769
  "draggable",
7770
+ "mod",
7245
7771
  "onClick"
7246
7772
  ]), unref(resize).isResizableEvent(event) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, renderList(["start", "end"], (edge) => {
7247
7773
  return createElementVNode("div", mergeProps({ key: edge }, { ref_for: true }, unref(staticStyles)("resourcesDayViewResizeHandle"), {
@@ -7287,6 +7813,7 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
7287
7813
  "data-business-hours": businessHoursMods.value[slotIndex]["business-hours"] || void 0,
7288
7814
  "data-non-business-hours": businessHoursMods.value[slotIndex]["non-business-hours"] || void 0,
7289
7815
  "data-drop-target": dropTarget.value?.resourceId === resource.id && dropTarget.value.slotIndex === slotIndex || void 0,
7816
+ "data-invalid": dropTarget.value?.resourceId === resource.id && dropTarget.value.slotIndex === slotIndex && !dropValid.value || void 0,
7290
7817
  "data-drag-selected": unref(slotSelect).isSlotSelected(slotIndex, String(resource.id)) || void 0,
7291
7818
  "data-static": isStatic.value || void 0,
7292
7819
  "data-drag-slot-index": unref(props).withDragSlotSelect ? slotIndex : void 0,
@@ -7317,6 +7844,7 @@ var ResourcesDayView = factory(/* @__PURE__ */ defineComponent({
7317
7844
  "data-business-hours",
7318
7845
  "data-non-business-hours",
7319
7846
  "data-drop-target",
7847
+ "data-invalid",
7320
7848
  "data-drag-selected",
7321
7849
  "data-static",
7322
7850
  "data-drag-slot-index",
@@ -7436,31 +7964,31 @@ function getResourcesWeekViewEvents({ events, resources, weekdays, startTime, en
7436
7964
  };
7437
7965
  }
7438
7966
  var ResourcesWeekView_module_default = {
7439
- resourcesWeekView: "_resourcesWeekView_1rg4q_1",
7440
- resourcesWeekViewRoot: "_resourcesWeekViewRoot_1rg4q_19",
7441
- resourcesWeekViewScrollArea: "_resourcesWeekViewScrollArea_1rg4q_26",
7442
- resourcesWeekViewInner: "_resourcesWeekViewInner_1rg4q_34",
7443
- resourcesWeekViewHeaderRows: "_resourcesWeekViewHeaderRows_1rg4q_39",
7444
- resourcesWeekViewCorner: "_resourcesWeekViewCorner_1rg4q_48",
7445
- resourcesWeekViewHeaderContent: "_resourcesWeekViewHeaderContent_1rg4q_63",
7446
- resourcesWeekViewDayLabelsRow: "_resourcesWeekViewDayLabelsRow_1rg4q_67",
7447
- resourcesWeekViewDayLabel: "_resourcesWeekViewDayLabel_1rg4q_67",
7448
- resourcesWeekViewTimeLabelsRow: "_resourcesWeekViewTimeLabelsRow_1rg4q_94",
7449
- resourcesWeekViewTimeLabel: "_resourcesWeekViewTimeLabel_1rg4q_94",
7450
- resourcesWeekViewRow: "_resourcesWeekViewRow_1rg4q_121",
7451
- resourcesWeekViewResourceLabel: "_resourcesWeekViewResourceLabel_1rg4q_125",
7452
- resourcesWeekViewGroupColumn: "_resourcesWeekViewGroupColumn_1rg4q_149",
7453
- resourcesWeekViewGroupColumnEmpty: "_resourcesWeekViewGroupColumnEmpty_1rg4q_150",
7454
- resourcesWeekViewRowSlots: "_resourcesWeekViewRowSlots_1rg4q_178",
7455
- resourcesWeekViewRowSlot: "_resourcesWeekViewRowSlot_1rg4q_178",
7456
- resourcesWeekViewBackgroundEvent: "_resourcesWeekViewBackgroundEvent_1rg4q_250",
7457
- resourcesWeekViewAllDayEvent: "_resourcesWeekViewAllDayEvent_1rg4q_278",
7458
- resourcesWeekViewEventWrapper: "_resourcesWeekViewEventWrapper_1rg4q_283",
7459
- resourcesWeekViewResizeHandle: "_resourcesWeekViewResizeHandle_1rg4q_287",
7460
- resourcesWeekViewCurrentTimeIndicator: "_resourcesWeekViewCurrentTimeIndicator_1rg4q_364",
7461
- resourcesWeekViewCurrentTimeIndicatorLine: "_resourcesWeekViewCurrentTimeIndicatorLine_1rg4q_376",
7462
- resourcesWeekViewCurrentTimeIndicatorThumb: "_resourcesWeekViewCurrentTimeIndicatorThumb_1rg4q_382",
7463
- resourcesWeekViewCurrentTimeIndicatorTimeBubble: "_resourcesWeekViewCurrentTimeIndicatorTimeBubble_1rg4q_392"
7967
+ resourcesWeekView: "_resourcesWeekView_1g2tz_1",
7968
+ resourcesWeekViewRoot: "_resourcesWeekViewRoot_1g2tz_19",
7969
+ resourcesWeekViewScrollArea: "_resourcesWeekViewScrollArea_1g2tz_26",
7970
+ resourcesWeekViewInner: "_resourcesWeekViewInner_1g2tz_34",
7971
+ resourcesWeekViewHeaderRows: "_resourcesWeekViewHeaderRows_1g2tz_39",
7972
+ resourcesWeekViewCorner: "_resourcesWeekViewCorner_1g2tz_48",
7973
+ resourcesWeekViewHeaderContent: "_resourcesWeekViewHeaderContent_1g2tz_63",
7974
+ resourcesWeekViewDayLabelsRow: "_resourcesWeekViewDayLabelsRow_1g2tz_67",
7975
+ resourcesWeekViewDayLabel: "_resourcesWeekViewDayLabel_1g2tz_67",
7976
+ resourcesWeekViewTimeLabelsRow: "_resourcesWeekViewTimeLabelsRow_1g2tz_94",
7977
+ resourcesWeekViewTimeLabel: "_resourcesWeekViewTimeLabel_1g2tz_94",
7978
+ resourcesWeekViewRow: "_resourcesWeekViewRow_1g2tz_121",
7979
+ resourcesWeekViewResourceLabel: "_resourcesWeekViewResourceLabel_1g2tz_125",
7980
+ resourcesWeekViewGroupColumn: "_resourcesWeekViewGroupColumn_1g2tz_149",
7981
+ resourcesWeekViewGroupColumnEmpty: "_resourcesWeekViewGroupColumnEmpty_1g2tz_150",
7982
+ resourcesWeekViewRowSlots: "_resourcesWeekViewRowSlots_1g2tz_178",
7983
+ resourcesWeekViewRowSlot: "_resourcesWeekViewRowSlot_1g2tz_178",
7984
+ resourcesWeekViewBackgroundEvent: "_resourcesWeekViewBackgroundEvent_1g2tz_259",
7985
+ resourcesWeekViewAllDayEvent: "_resourcesWeekViewAllDayEvent_1g2tz_287",
7986
+ resourcesWeekViewEventWrapper: "_resourcesWeekViewEventWrapper_1g2tz_292",
7987
+ resourcesWeekViewResizeHandle: "_resourcesWeekViewResizeHandle_1g2tz_296",
7988
+ resourcesWeekViewCurrentTimeIndicator: "_resourcesWeekViewCurrentTimeIndicator_1g2tz_373",
7989
+ resourcesWeekViewCurrentTimeIndicatorLine: "_resourcesWeekViewCurrentTimeIndicatorLine_1g2tz_385",
7990
+ resourcesWeekViewCurrentTimeIndicatorThumb: "_resourcesWeekViewCurrentTimeIndicatorThumb_1g2tz_391",
7991
+ resourcesWeekViewCurrentTimeIndicatorTimeBubble: "_resourcesWeekViewCurrentTimeIndicatorTimeBubble_1g2tz_401"
7464
7992
  };
7465
7993
  //#endregion
7466
7994
  //#region src/components/ResourcesWeekView/ResourcesWeekView.vue?vue&type=script&setup=true&lang.ts
@@ -7594,6 +8122,10 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
7594
8122
  type: Function,
7595
8123
  default: void 0
7596
8124
  },
8125
+ canDropEvent: {},
8126
+ canDropExternalEvent: {},
8127
+ canResizeEventTo: {},
8128
+ preventEventOverlap: { type: [Boolean, Function] },
7597
8129
  recurrenceExpansionLimit: { default: void 0 },
7598
8130
  maxEventsPerTimeSlot: { default: void 0 },
7599
8131
  moreEventsProps: { default: void 0 },
@@ -7626,7 +8158,8 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
7626
8158
  "timeSlotClick",
7627
8159
  "slotDragEnd",
7628
8160
  "externalEventDrop",
7629
- "eventResize"
8161
+ "eventResize",
8162
+ "eventPlacementRejected"
7630
8163
  ],
7631
8164
  setup(__props, { emit: __emit }) {
7632
8165
  const rawProps = __props;
@@ -7670,6 +8203,7 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
7670
8203
  rootElement.value = node instanceof HTMLElement ? node : null;
7671
8204
  };
7672
8205
  const dropTarget = shallowRef(null);
8206
+ const dropValid = ref(true);
7673
8207
  const scrolledX = ref(false);
7674
8208
  const isStatic = computed(() => props.mode === "static");
7675
8209
  const intervals = computed(() => getDayTimeIntervals({
@@ -7758,6 +8292,10 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
7758
8292
  resizeIntervalMinutes: () => props.eventResizeInterval,
7759
8293
  onEventResize: (data) => emit("eventResize", data),
7760
8294
  canResizeEvent: () => props.canResizeEvent,
8295
+ events: () => props.events ?? [],
8296
+ preventEventOverlap: () => props.preventEventOverlap,
8297
+ canResizeEventTo: () => props.canResizeEventTo,
8298
+ onEventPlacementRejected: (data) => emit("eventPlacementRejected", data),
7761
8299
  withBackgroundEvents: () => Boolean(props.withInteractiveBackgroundEvents)
7762
8300
  });
7763
8301
  onMounted(async () => {
@@ -7800,15 +8338,51 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
7800
8338
  if (!day || !interval) return;
7801
8339
  const target = getSnappedDropTarget(nativeEvent, day, flatIndex, interval.startTime);
7802
8340
  const event = getDropEvent(props.events, nativeEvent.dataTransfer);
7803
- if (event) emit("eventDrop", {
7804
- ...moveEventTo(event, target),
8341
+ if (event) {
8342
+ const next = moveEventTo(event, target);
8343
+ const validation = isEventPlacementAllowed({
8344
+ event,
8345
+ start: next.newStart,
8346
+ end: next.newEnd,
8347
+ events: props.events ?? [],
8348
+ preventEventOverlap: props.preventEventOverlap,
8349
+ resourceId
8350
+ });
8351
+ if (validation.allowed && props.canDropEvent?.({
8352
+ event,
8353
+ start: next.newStart,
8354
+ end: next.newEnd,
8355
+ resourceId
8356
+ }) !== false) emit("eventDrop", {
8357
+ ...next,
8358
+ resourceId
8359
+ });
8360
+ else emit("eventPlacementRejected", {
8361
+ action: "drop",
8362
+ event,
8363
+ start: next.newStart,
8364
+ end: next.newEnd,
8365
+ resourceId,
8366
+ conflicts: validation.conflicts,
8367
+ reason: validation.allowed ? "rejected" : "overlap"
8368
+ });
8369
+ } else if (nativeEvent.dataTransfer) if (props.canDropExternalEvent?.({
8370
+ dataTransfer: nativeEvent.dataTransfer,
8371
+ start: target,
7805
8372
  resourceId
7806
- });
7807
- else if (nativeEvent.dataTransfer) emit("externalEventDrop", {
8373
+ }) !== false) emit("externalEventDrop", {
7808
8374
  dataTransfer: nativeEvent.dataTransfer,
7809
8375
  dropDateTime: target,
7810
8376
  resourceId
7811
8377
  });
8378
+ else emit("eventPlacementRejected", {
8379
+ action: "external-drop",
8380
+ dataTransfer: nativeEvent.dataTransfer,
8381
+ start: target,
8382
+ resourceId,
8383
+ conflicts: [],
8384
+ reason: "rejected"
8385
+ });
7812
8386
  };
7813
8387
  const getSnappedDropTarget = (nativeEvent, day, flatIndex, slotStartTime) => {
7814
8388
  if (props.eventDragInterval == null) return `${day} ${slotStartTime}`;
@@ -7839,6 +8413,31 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
7839
8413
  */
7840
8414
  const resolveDropTarget = rafThrottle((nativeEvent, resourceId, resourceIndex) => {
7841
8415
  const flatIndex = getFlatIndexAtPoint(nativeEvent, resourceIndex);
8416
+ const count = slotsPerDay.value;
8417
+ const day = weekdays.value[Math.floor(flatIndex / count)];
8418
+ const interval = intervals.value[flatIndex % count];
8419
+ const target = flatIndex >= 0 && day && interval ? getSnappedDropTarget(nativeEvent, day, flatIndex, interval.startTime) : null;
8420
+ const event = dragState.draggedEvent.value;
8421
+ if (target && event) {
8422
+ const next = moveEventTo(event, target);
8423
+ dropValid.value = isEventPlacementAllowed({
8424
+ event,
8425
+ start: next.newStart,
8426
+ end: next.newEnd,
8427
+ events: props.events ?? [],
8428
+ preventEventOverlap: props.preventEventOverlap,
8429
+ resourceId
8430
+ }).allowed && props.canDropEvent?.({
8431
+ event,
8432
+ start: next.newStart,
8433
+ end: next.newEnd,
8434
+ resourceId
8435
+ }) !== false;
8436
+ } else if (target && nativeEvent.dataTransfer) dropValid.value = props.canDropExternalEvent?.({
8437
+ dataTransfer: nativeEvent.dataTransfer,
8438
+ start: target,
8439
+ resourceId
8440
+ }) !== false;
7842
8441
  setDropTarget(flatIndex < 0 ? null : {
7843
8442
  resourceId,
7844
8443
  flatIndex
@@ -8200,7 +8799,8 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
8200
8799
  style: {
8201
8800
  width: "100%",
8202
8801
  height: "100%"
8203
- }
8802
+ },
8803
+ mod: { invalid: unref(resize).getResizePosition(entry.event.id) !== null && !unref(resize).resizeValid.value }
8204
8804
  }, { ref_for: true }, {
8205
8805
  ...eventRenderers.value,
8206
8806
  ...stylesApi.value
@@ -8213,6 +8813,7 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
8213
8813
  "radius",
8214
8814
  "mode",
8215
8815
  "draggable",
8816
+ "mod",
8216
8817
  "onClick"
8217
8818
  ]), unref(resize).isResizableEvent(entry.event) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, renderList(["start", "end"], (edge) => {
8218
8819
  return createElementVNode("div", mergeProps({ key: edge }, { ref_for: true }, unref(staticStyles)("resourcesWeekViewResizeHandle"), {
@@ -8260,6 +8861,7 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
8260
8861
  "data-business-hours": businessHoursMods.value[dayIndex][slotIndex]["business-hours"] || void 0,
8261
8862
  "data-non-business-hours": businessHoursMods.value[dayIndex][slotIndex]["non-business-hours"] || void 0,
8262
8863
  "data-drop-target": dropTarget.value?.resourceId === resource.id && dropTarget.value.flatIndex === dayIndex * slotsPerDay.value + slotIndex || void 0,
8864
+ "data-invalid": dropTarget.value?.resourceId === resource.id && dropTarget.value.flatIndex === dayIndex * slotsPerDay.value + slotIndex && !dropValid.value || void 0,
8263
8865
  "data-drag-selected": unref(slotSelect).isSlotSelected(dayIndex * slotsPerDay.value + slotIndex, String(resource.id)) || void 0,
8264
8866
  "data-static": isStatic.value || void 0,
8265
8867
  "data-drag-slot-index": unref(props).withDragSlotSelect ? dayIndex * slotsPerDay.value + slotIndex : void 0,
@@ -8291,6 +8893,7 @@ var ResourcesWeekView = factory(/* @__PURE__ */ defineComponent({
8291
8893
  "data-business-hours",
8292
8894
  "data-non-business-hours",
8293
8895
  "data-drop-target",
8896
+ "data-invalid",
8294
8897
  "data-drag-selected",
8295
8898
  "data-static",
8296
8899
  "data-drag-slot-index",
@@ -8420,23 +9023,23 @@ function getResourcesMonthViewLayout({ days, events, resourceId, maxRows }) {
8420
9023
  };
8421
9024
  }
8422
9025
  var ResourcesMonthView_module_default = {
8423
- resourcesMonthView: "_resourcesMonthView_uqbdi_1",
8424
- resourcesMonthViewRoot: "_resourcesMonthViewRoot_uqbdi_17",
8425
- resourcesMonthViewScrollArea: "_resourcesMonthViewScrollArea_uqbdi_24",
8426
- resourcesMonthViewInner: "_resourcesMonthViewInner_uqbdi_33",
8427
- resourcesMonthViewDayLabelsRow: "_resourcesMonthViewDayLabelsRow_uqbdi_37",
8428
- resourcesMonthViewCorner: "_resourcesMonthViewCorner_uqbdi_46",
8429
- resourcesMonthViewDayLabel: "_resourcesMonthViewDayLabel_uqbdi_37",
8430
- resourcesMonthViewDayLabelWeekday: "_resourcesMonthViewDayLabelWeekday_uqbdi_85",
8431
- resourcesMonthViewDayLabelNumber: "_resourcesMonthViewDayLabelNumber_uqbdi_92",
8432
- resourcesMonthViewRow: "_resourcesMonthViewRow_uqbdi_97",
8433
- resourcesMonthViewResourceLabel: "_resourcesMonthViewResourceLabel_uqbdi_101",
8434
- resourcesMonthViewGroupColumn: "_resourcesMonthViewGroupColumn_uqbdi_120",
8435
- resourcesMonthViewGroupColumnEmpty: "_resourcesMonthViewGroupColumnEmpty_uqbdi_121",
8436
- resourcesMonthViewRowSlots: "_resourcesMonthViewRowSlots_uqbdi_149",
8437
- resourcesMonthViewCell: "_resourcesMonthViewCell_uqbdi_154",
8438
- resourcesMonthViewEventWrapper: "_resourcesMonthViewEventWrapper_uqbdi_230",
8439
- resourcesMonthViewResizeHandle: "_resourcesMonthViewResizeHandle_uqbdi_231"
9026
+ resourcesMonthView: "_resourcesMonthView_1rka1_1",
9027
+ resourcesMonthViewRoot: "_resourcesMonthViewRoot_1rka1_17",
9028
+ resourcesMonthViewScrollArea: "_resourcesMonthViewScrollArea_1rka1_24",
9029
+ resourcesMonthViewInner: "_resourcesMonthViewInner_1rka1_33",
9030
+ resourcesMonthViewDayLabelsRow: "_resourcesMonthViewDayLabelsRow_1rka1_37",
9031
+ resourcesMonthViewCorner: "_resourcesMonthViewCorner_1rka1_46",
9032
+ resourcesMonthViewDayLabel: "_resourcesMonthViewDayLabel_1rka1_37",
9033
+ resourcesMonthViewDayLabelWeekday: "_resourcesMonthViewDayLabelWeekday_1rka1_85",
9034
+ resourcesMonthViewDayLabelNumber: "_resourcesMonthViewDayLabelNumber_1rka1_92",
9035
+ resourcesMonthViewRow: "_resourcesMonthViewRow_1rka1_97",
9036
+ resourcesMonthViewResourceLabel: "_resourcesMonthViewResourceLabel_1rka1_101",
9037
+ resourcesMonthViewGroupColumn: "_resourcesMonthViewGroupColumn_1rka1_120",
9038
+ resourcesMonthViewGroupColumnEmpty: "_resourcesMonthViewGroupColumnEmpty_1rka1_121",
9039
+ resourcesMonthViewRowSlots: "_resourcesMonthViewRowSlots_1rka1_149",
9040
+ resourcesMonthViewCell: "_resourcesMonthViewCell_1rka1_154",
9041
+ resourcesMonthViewEventWrapper: "_resourcesMonthViewEventWrapper_1rka1_239",
9042
+ resourcesMonthViewResizeHandle: "_resourcesMonthViewResizeHandle_1rka1_240"
8440
9043
  };
8441
9044
  //#endregion
8442
9045
  //#region src/components/ResourcesMonthView/ResourcesMonthView.vue?vue&type=script&setup=true&lang.ts
@@ -8545,6 +9148,10 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8545
9148
  type: Function,
8546
9149
  default: void 0
8547
9150
  },
9151
+ canDropEvent: {},
9152
+ canDropExternalEvent: {},
9153
+ canResizeEventTo: {},
9154
+ preventEventOverlap: { type: [Boolean, Function] },
8548
9155
  withExternalEventDrop: { type: Boolean },
8549
9156
  withDragSlotSelect: { type: Boolean },
8550
9157
  labels: { default: void 0 },
@@ -8568,7 +9175,8 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8568
9175
  "eventDragEnd",
8569
9176
  "slotDragEnd",
8570
9177
  "externalEventDrop",
8571
- "eventResize"
9178
+ "eventResize",
9179
+ "eventPlacementRejected"
8572
9180
  ],
8573
9181
  setup(__props, { emit: __emit }) {
8574
9182
  const rawProps = __props;
@@ -8612,6 +9220,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8612
9220
  rootElement.value = node instanceof HTMLElement ? node : null;
8613
9221
  };
8614
9222
  const dropTarget = shallowRef(null);
9223
+ const dropValid = ref(true);
8615
9224
  const isStatic = computed(() => props.mode === "static");
8616
9225
  const month = computed(() => dayjs(props.date).startOf("month"));
8617
9226
  const monthString = computed(() => month.value.format("YYYY-MM-DD"));
@@ -8627,6 +9236,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8627
9236
  expansionLimit: props.recurrenceExpansionLimit
8628
9237
  }));
8629
9238
  const resizeState = shallowRef(null);
9239
+ const resizeValid = ref(true);
8630
9240
  let justResized = false;
8631
9241
  const effectiveEvents = computed(() => {
8632
9242
  const state = resizeState.value;
@@ -8699,18 +9309,57 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8699
9309
  draggedEvent: dragged,
8700
9310
  targetDay: day
8701
9311
  });
8702
- emit("eventDrop", {
9312
+ const start = dayjs(next.start).format("YYYY-MM-DD HH:mm:ss");
9313
+ const end = dayjs(next.end).format("YYYY-MM-DD HH:mm:ss");
9314
+ const validation = isEventPlacementAllowed({
9315
+ event: dragged,
9316
+ start,
9317
+ end,
9318
+ events: expandedEvents.value,
9319
+ preventEventOverlap: props.preventEventOverlap,
9320
+ resourceId
9321
+ });
9322
+ if (validation.allowed && props.canDropEvent?.({
9323
+ event: dragged,
9324
+ start,
9325
+ end,
9326
+ resourceId
9327
+ }) !== false) emit("eventDrop", {
8703
9328
  eventId: dragged.id,
8704
- newStart: dayjs(next.start).format("YYYY-MM-DD HH:mm:ss"),
8705
- newEnd: dayjs(next.end).format("YYYY-MM-DD HH:mm:ss"),
9329
+ newStart: start,
9330
+ newEnd: end,
8706
9331
  event: dragged,
8707
9332
  resourceId
8708
9333
  });
8709
- } else if (nativeEvent.dataTransfer) emit("externalEventDrop", {
8710
- dataTransfer: nativeEvent.dataTransfer,
8711
- dropDateTime: `${day} 00:00:00`,
8712
- resourceId
8713
- });
9334
+ else emit("eventPlacementRejected", {
9335
+ action: "drop",
9336
+ event: dragged,
9337
+ start,
9338
+ end,
9339
+ resourceId,
9340
+ conflicts: validation.conflicts,
9341
+ reason: validation.allowed ? "rejected" : "overlap"
9342
+ });
9343
+ } else if (nativeEvent.dataTransfer) {
9344
+ const start = `${day} 00:00:00`;
9345
+ if (props.canDropExternalEvent?.({
9346
+ dataTransfer: nativeEvent.dataTransfer,
9347
+ start,
9348
+ resourceId
9349
+ }) !== false) emit("externalEventDrop", {
9350
+ dataTransfer: nativeEvent.dataTransfer,
9351
+ dropDateTime: start,
9352
+ resourceId
9353
+ });
9354
+ else emit("eventPlacementRejected", {
9355
+ action: "external-drop",
9356
+ dataTransfer: nativeEvent.dataTransfer,
9357
+ start,
9358
+ resourceId,
9359
+ conflicts: [],
9360
+ reason: "rejected"
9361
+ });
9362
+ }
8714
9363
  };
8715
9364
  const setDropTarget = (next) => {
8716
9365
  const current = dropTarget.value;
@@ -8725,6 +9374,36 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8725
9374
  */
8726
9375
  const resolveDropTarget = rafThrottle((nativeEvent, resourceId, resourceIndex) => {
8727
9376
  const dayIndex = indexAtPoint(nativeEvent, resourceIndex);
9377
+ const day = days.value[dayIndex];
9378
+ const dragged = dragState.draggedEvent.value;
9379
+ if (day && dragged) {
9380
+ const next = calculateMonthDropDate({
9381
+ draggedEvent: dragged,
9382
+ targetDay: day
9383
+ });
9384
+ const start = dayjs(next.start).format("YYYY-MM-DD HH:mm:ss");
9385
+ const end = dayjs(next.end).format("YYYY-MM-DD HH:mm:ss");
9386
+ dropValid.value = isEventPlacementAllowed({
9387
+ event: dragged,
9388
+ start,
9389
+ end,
9390
+ events: expandedEvents.value,
9391
+ preventEventOverlap: props.preventEventOverlap,
9392
+ resourceId
9393
+ }).allowed && props.canDropEvent?.({
9394
+ event: dragged,
9395
+ start,
9396
+ end,
9397
+ resourceId
9398
+ }) !== false;
9399
+ } else if (day && nativeEvent.dataTransfer) {
9400
+ const start = `${day} 00:00:00`;
9401
+ dropValid.value = props.canDropExternalEvent?.({
9402
+ dataTransfer: nativeEvent.dataTransfer,
9403
+ start,
9404
+ resourceId
9405
+ }) !== false;
9406
+ }
8728
9407
  setDropTarget(dayIndex < 0 ? null : {
8729
9408
  resourceId,
8730
9409
  dayIndex
@@ -8847,6 +9526,16 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8847
9526
  ...calculateResizeDates(state.event, state.edge, days.value[dayIndex]),
8848
9527
  dayIndex
8849
9528
  };
9529
+ resizeValid.value = validateEventResize({
9530
+ event: state.event,
9531
+ start: resizeState.value.start,
9532
+ end: resizeState.value.end,
9533
+ edge: state.edge,
9534
+ events: expandedEvents.value,
9535
+ preventEventOverlap: props.preventEventOverlap,
9536
+ canResizeEventTo: props.canResizeEventTo,
9537
+ resourceId: state.event.resourceId
9538
+ }).valid;
8850
9539
  };
8851
9540
  const stopResizeListeners = () => {
8852
9541
  document.removeEventListener("pointermove", handleResizeMove);
@@ -8857,12 +9546,33 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8857
9546
  const state = resizeState.value;
8858
9547
  stopResizeListeners();
8859
9548
  resizeState.value = null;
8860
- if (emitChange && state && (state.start !== state.originalStart || state.end !== state.originalEnd)) emit("eventResize", {
8861
- eventId: state.event.id,
8862
- newStart: state.start,
8863
- newEnd: state.end,
8864
- event: state.event
8865
- });
9549
+ if (emitChange && state && (state.start !== state.originalStart || state.end !== state.originalEnd)) {
9550
+ const validation = validateEventResize({
9551
+ event: state.event,
9552
+ start: state.start,
9553
+ end: state.end,
9554
+ edge: state.edge,
9555
+ events: expandedEvents.value,
9556
+ preventEventOverlap: props.preventEventOverlap,
9557
+ canResizeEventTo: props.canResizeEventTo,
9558
+ resourceId: state.event.resourceId
9559
+ });
9560
+ if (validation.valid) emit("eventResize", {
9561
+ eventId: state.event.id,
9562
+ newStart: state.start,
9563
+ newEnd: state.end,
9564
+ event: state.event
9565
+ });
9566
+ else emit("eventPlacementRejected", {
9567
+ action: "resize",
9568
+ event: state.event,
9569
+ start: state.start,
9570
+ end: state.end,
9571
+ edge: state.edge,
9572
+ conflicts: validation.conflicts,
9573
+ reason: validation.reason
9574
+ });
9575
+ }
8866
9576
  justResized = true;
8867
9577
  requestAnimationFrame(() => justResized = false);
8868
9578
  };
@@ -8888,6 +9598,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
8888
9598
  end,
8889
9599
  dayIndex: -1
8890
9600
  };
9601
+ resizeValid.value = true;
8891
9602
  document.addEventListener("pointermove", handleResizeMove);
8892
9603
  document.addEventListener("pointerup", handleResizeEnd);
8893
9604
  document.addEventListener("pointercancel", handleResizeCancel);
@@ -9016,6 +9727,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
9016
9727
  mode: unref(props).mode,
9017
9728
  draggable: isDraggableEvent(entry.event),
9018
9729
  "is-resizing": isResizingEvent(entry.event),
9730
+ mod: { invalid: isResizingEvent(entry.event) && !resizeValid.value },
9019
9731
  style: {
9020
9732
  "width": "100%",
9021
9733
  "height": "100%"
@@ -9033,6 +9745,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
9033
9745
  "mode",
9034
9746
  "draggable",
9035
9747
  "is-resizing",
9748
+ "mod",
9036
9749
  "onClick"
9037
9750
  ]),
9038
9751
  isResizableEvent(entry.event) ? (openBlock(), createElementBlock("div", mergeProps({
@@ -9070,6 +9783,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
9070
9783
  mode: unref(props).mode,
9071
9784
  draggable: isDraggableEvent(segment.event),
9072
9785
  "is-resizing": isResizingEvent(segment.event),
9786
+ mod: { invalid: isResizingEvent(segment.event) && !resizeValid.value },
9073
9787
  style: {
9074
9788
  "width": "100%",
9075
9789
  "height": "100%"
@@ -9088,6 +9802,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
9088
9802
  "mode",
9089
9803
  "draggable",
9090
9804
  "is-resizing",
9805
+ "mod",
9091
9806
  "onClick"
9092
9807
  ]),
9093
9808
  isResizableEvent(segment.event) && segment.hanging !== "start" && segment.hanging !== "both" ? (openBlock(), createElementBlock("div", mergeProps({
@@ -9143,6 +9858,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
9143
9858
  }, { ref_for: true }, unref(staticStyles)("resourcesMonthViewCell"), {
9144
9859
  "data-weekend": unref(props).weekendDays.includes(unref(dayjs)(day).day()) || void 0,
9145
9860
  "data-drop-target": dropTarget.value?.resourceId === resource.id && dropTarget.value.dayIndex === dayIndex || void 0,
9861
+ "data-invalid": dropTarget.value?.resourceId === resource.id && dropTarget.value.dayIndex === dayIndex && !dropValid.value || void 0,
9146
9862
  "data-drag-selected": unref(slotSelect).isSlotSelected(dayIndex, String(resource.id)) || void 0,
9147
9863
  "data-static": isStatic.value || void 0,
9148
9864
  "data-drag-slot-index": unref(props).withDragSlotSelect ? dayIndex : void 0,
@@ -9170,6 +9886,7 @@ var ResourcesMonthView = factory(/* @__PURE__ */ defineComponent({
9170
9886
  }, 1040, [
9171
9887
  "data-weekend",
9172
9888
  "data-drop-target",
9889
+ "data-invalid",
9173
9890
  "data-drag-selected",
9174
9891
  "data-static",
9175
9892
  "data-drag-slot-index",
@@ -9241,6 +9958,22 @@ var ResourcesSchedule = factory(/* @__PURE__ */ defineComponent({
9241
9958
  type: Function,
9242
9959
  default: void 0
9243
9960
  },
9961
+ canDropEvent: {
9962
+ type: Function,
9963
+ default: void 0
9964
+ },
9965
+ canDropExternalEvent: {
9966
+ type: Function,
9967
+ default: void 0
9968
+ },
9969
+ canResizeEventTo: {
9970
+ type: Function,
9971
+ default: void 0
9972
+ },
9973
+ preventEventOverlap: {
9974
+ type: [Boolean, Function],
9975
+ default: void 0
9976
+ },
9244
9977
  withInteractiveBackgroundEvents: {
9245
9978
  type: Boolean,
9246
9979
  default: void 0
@@ -9267,7 +10000,8 @@ var ResourcesSchedule = factory(/* @__PURE__ */ defineComponent({
9267
10000
  "dayClick",
9268
10001
  "slotDragEnd",
9269
10002
  "externalEventDrop",
9270
- "eventResize"
10003
+ "eventResize",
10004
+ "eventPlacementRejected"
9271
10005
  ],
9272
10006
  setup(__props, { emit: __emit }) {
9273
10007
  const rawProps = __props;
@@ -9329,6 +10063,9 @@ var ResourcesSchedule = factory(/* @__PURE__ */ defineComponent({
9329
10063
  renderResourceLabel: props.renderResourceLabel,
9330
10064
  withEventsDragAndDrop: isStatic.value ? false : props.withEventsDragAndDrop,
9331
10065
  canDragEvent: props.canDragEvent,
10066
+ canDropEvent: props.canDropEvent,
10067
+ canDropExternalEvent: props.canDropExternalEvent,
10068
+ preventEventOverlap: props.preventEventOverlap,
9332
10069
  withDragSlotSelect: props.withDragSlotSelect,
9333
10070
  recurrenceExpansionLimit: props.recurrenceExpansionLimit,
9334
10071
  withInteractiveBackgroundEvents: isStatic.value ? false : props.withInteractiveBackgroundEvents,
@@ -9340,6 +10077,7 @@ var ResourcesSchedule = factory(/* @__PURE__ */ defineComponent({
9340
10077
  onEventClick: (event, nativeEvent) => emit("eventClick", event, nativeEvent),
9341
10078
  onSlotDragEnd: (data) => emit("slotDragEnd", data),
9342
10079
  onExternalEventDrop: (data) => emit("externalEventDrop", data),
10080
+ onEventPlacementRejected: (data) => emit("eventPlacementRejected", data),
9343
10081
  ...eventRenderers.value,
9344
10082
  ...stylesApi.value
9345
10083
  }));
@@ -9347,6 +10085,7 @@ var ResourcesSchedule = factory(/* @__PURE__ */ defineComponent({
9347
10085
  onTimeSlotClick: (data) => emit("timeSlotClick", data),
9348
10086
  withEventResize: isStatic.value ? false : props.withEventResize,
9349
10087
  canResizeEvent: props.canResizeEvent,
10088
+ canResizeEventTo: props.canResizeEventTo,
9350
10089
  onEventResize: (data) => emit("eventResize", data)
9351
10090
  }));
9352
10091
  const activeView = computed(() => {
@@ -9406,6 +10145,6 @@ var ResourcesSchedule = factory(/* @__PURE__ */ defineComponent({
9406
10145
  }
9407
10146
  }), { classes: ResourcesSchedule_module_default });
9408
10147
  //#endregion
9409
- export { CurrentTimeIndicator, DEFAULT_SCHEDULE_LABELS, DayView, DragContext, HeaderControl, MobileMonthView, MonthView, MonthYearSelect, MoreEvents, ResourcesDayView, ResourcesMonthView, ResourcesSchedule, ResourcesWeekView, Schedule, ScheduleBackgroundEvent_default as ScheduleBackgroundEvent, ScheduleEvent, ScheduleHeader, ScheduleHeaderBase, ScheduleHeaderNext, ScheduleHeaderPrevious, ScheduleHeaderToday, ViewSelect, WeekView, YearView, applyCascadeLayout, calculateDropTime, calculateMonthDropDate, clampIntervalMinutes, compareMonthEvents, createHeaderNavigation, expandRecurringEvents, formatDate, getBusinessHoursMod, getCurrentTimePosition, getDayPosition, getDayPositionedEvents, getDayTimeIntervals, getDayViewEvents, getEndOfWeek, getGroupToResourceIdMap, getLabel, getMonthDays, getMonthPositionedEvents, getMonthRange, getMonthViewEvents, getMonthsByQuarter, getMonthsList, getOrderedResources, getOverlapClusters, getRenderableMonthEventSegments, getResourcesDayViewEvents, getResourcesMonthViewLayout, getResourcesWeekViewEvents, getStartOfWeek, getVisibleEvents, getWeekDays, getWeekLabel, getWeekNumber, getWeekPositionedEvents, getWeekViewEvents, getWeekdaysNames, getYearsList, handleResourcesGridKeyDown, isAfterMinDate, isAllDayEvent, isBeforeMaxDate, isEventInTimeRange, isEventsOverlap, isInTimeRange, isMultiDayEvent, isMultidayEvent, isSameMonth, isWithinWeek, nextWeek, parseTimeString, previousWeek, provideDragContext, provideScheduleDragState, sortEvents, toDateString, toTimeString, useDragContext, useScheduleHeaderLabels, validateEvent };
10148
+ export { CurrentTimeIndicator, DEFAULT_SCHEDULE_LABELS, DayView, DragContext, HeaderControl, MobileMonthView, MonthView, MonthYearSelect, MoreEvents, ResourcesDayView, ResourcesMonthView, ResourcesSchedule, ResourcesWeekView, Schedule, ScheduleBackgroundEvent_default as ScheduleBackgroundEvent, ScheduleEvent, ScheduleHeader, ScheduleHeaderBase, ScheduleHeaderNext, ScheduleHeaderPrevious, ScheduleHeaderToday, ViewSelect, WeekView, YearView, applyCascadeLayout, calculateDropTime, calculateMonthDropDate, clampIntervalMinutes, compareMonthEvents, createHeaderNavigation, expandRecurringEvents, formatDate, getBusinessHoursMod, getCurrentTimePosition, getDayPosition, getDayPositionedEvents, getDayTimeIntervals, getDayViewEvents, getEndOfWeek, getGroupToResourceIdMap, getLabel, getMonthDays, getMonthPositionedEvents, getMonthRange, getMonthViewEvents, getMonthsByQuarter, getMonthsList, getOrderedResources, getOverlapClusters, getRenderableMonthEventSegments, getResourcesDayViewEvents, getResourcesMonthViewLayout, getResourcesWeekViewEvents, getStartOfWeek, getVisibleEvents, getWeekDays, getWeekLabel, getWeekNumber, getWeekPositionedEvents, getWeekViewEvents, getWeekdaysNames, getYearsList, handleResourcesGridKeyDown, isAfterMinDate, isAllDayEvent, isBeforeMaxDate, isEventInTimeRange, isEventPlacementAllowed, isEventsOverlap, isInTimeRange, isMultiDayEvent, isMultidayEvent, isSameMonth, isWithinWeek, nextWeek, parseTimeString, previousWeek, provideDragContext, provideScheduleDragState, sortEvents, toDateString, toTimeString, useDragContext, useScheduleHeaderLabels, validateEvent };
9410
10149
 
9411
10150
  //# sourceMappingURL=index.mjs.map