@primeui/scheduler-core 0.0.1-alpha.1 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +35 -0
- package/README.md +12 -0
- package/THIRD-PARTY-NOTICES.txt +191 -0
- package/dist/{overlay-BYM9B6nC.d.mts → appointment-slots-DCiNFFed.d.mts} +2 -13
- package/dist/calendar/index.mjs +1 -1
- package/dist/{chunk-NMX4BW42.mjs → chunks/chunk-2YXHUV2A.mjs} +2 -2
- package/dist/{chunk-FIBAZFC4.mjs → chunks/chunk-6Q5FR4PN.mjs} +1 -1
- package/dist/{chunk-NX46LPLF.mjs → chunks/chunk-BJFVXDZC.mjs} +2 -2
- package/dist/{chunk-6PK5WSKT.mjs → chunks/chunk-EHH5ARHF.mjs} +29 -35
- package/dist/{chunk-TNKJPFGI.mjs → chunks/chunk-F2LYNUXG.mjs} +1 -1
- package/dist/{chunk-ZUKUKGNK.mjs → chunks/chunk-G7F2OBHW.mjs} +30 -34
- package/dist/{chunk-KQGRXTP5.mjs → chunks/chunk-HF32DKZY.mjs} +26 -270
- package/dist/chunks/chunk-HWGXSE6Q.mjs +269 -0
- package/dist/{chunk-HPC5B3AR.mjs → chunks/chunk-JCNXNPGM.mjs} +3 -3
- package/dist/{chunk-6OZAPQZ5.mjs → chunks/chunk-LMZ2J5Z5.mjs} +3 -3
- package/dist/{chunk-F5W5HD7S.mjs → chunks/chunk-LYPP7W7B.mjs} +79 -7
- package/dist/{chunk-W2SJW3QQ.mjs → chunks/chunk-NKSMQCWJ.mjs} +21 -50
- package/dist/{chunk-6VYWVIGM.mjs → chunks/chunk-QBTFRSZM.mjs} +5 -5
- package/dist/{chunk-NZGJN7HG.mjs → chunks/chunk-RM6OQCEO.mjs} +2 -2
- package/dist/{chunk-2THQAZ26.mjs → chunks/chunk-URRTAW2Q.mjs} +7 -54
- package/dist/{chunk-WFUJWDST.mjs → chunks/chunk-XQAYO7CQ.mjs} +1 -1
- package/dist/controllers/index.d.mts +3 -3
- package/dist/controllers/index.mjs +946 -13
- package/dist/event/index.mjs +8 -8
- package/dist/index.d.mts +6 -13
- package/dist/index.mjs +32 -34
- package/dist/interaction/index.d.mts +2 -63
- package/dist/interaction/index.mjs +9 -9
- package/dist/month/index.mjs +6 -6
- package/dist/resource/index.mjs +1 -1
- package/dist/time-grid/index.d.mts +9 -2
- package/dist/time-grid/index.mjs +12 -13
- package/dist/timeline/index.d.mts +11 -1
- package/dist/timeline/index.mjs +7 -6
- package/dist/{touch-BhsMWsjf.d.mts → touch-B6xcJlyY.d.mts} +1 -1
- package/dist/utils/index.d.mts +2 -27
- package/dist/utils/index.mjs +16 -17
- package/dist/views/index.mjs +8 -8
- package/dist/views/timeline/index.mjs +4 -4
- package/dist/year/index.mjs +6 -6
- package/package.json +61 -10
- package/LICENSE +0 -23
- package/dist/chunk-5N4ZOBJV.mjs +0 -866
- package/dist/chunk-AAVM7UCG.mjs +0 -100
- /package/dist/{chunk-DYW6WUHE.mjs → chunks/chunk-6OTDPEJM.mjs} +0 -0
- /package/dist/{chunk-UMAMDBU4.mjs → chunks/chunk-73ID2V6E.mjs} +0 -0
- /package/dist/{chunk-C7ADJGNV.mjs → chunks/chunk-7TCZNLG7.mjs} +0 -0
- /package/dist/{chunk-5KORIWDT.mjs → chunks/chunk-AZRI6PHU.mjs} +0 -0
- /package/dist/{chunk-XUBQ2IQS.mjs → chunks/chunk-B4YDYPVO.mjs} +0 -0
- /package/dist/{chunk-SYJ5O4KH.mjs → chunks/chunk-IJH6YR4N.mjs} +0 -0
- /package/dist/{chunk-QDMZBJDV.mjs → chunks/chunk-P7CIUMQZ.mjs} +0 -0
- /package/dist/{chunk-2B3YLWHA.mjs → chunks/chunk-UKD2NVDC.mjs} +0 -0
- /package/dist/{chunk-QR2SVYAD.mjs → chunks/chunk-XMU4WSAX.mjs} +0 -0
package/dist/chunk-5N4ZOBJV.mjs
DELETED
|
@@ -1,866 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_DRAG_MIN_DISTANCE, applyDeltaToEvent, findOverlappingEvents, applyResizeToEvent, detectResizeEdge, createResizeState, createDragState, snapToSlot, getYPositionFromTime, getSchedulerTimelineResizePreview } from './chunk-2THQAZ26.mjs';
|
|
2
|
-
import { hasOverlapInAnyAssignedResource, getEventResourceIds } from './chunk-SYJ5O4KH.mjs';
|
|
3
|
-
import { updateSlotsAvailability, getSlotsForTimeRange } from './chunk-NZGJN7HG.mjs';
|
|
4
|
-
import { canDropEvent } from './chunk-HPC5B3AR.mjs';
|
|
5
|
-
import { getSchedulerEventSurfaceStyle } from './chunk-5KORIWDT.mjs';
|
|
6
|
-
import { addDays, isSameDay } from './chunk-WFUJWDST.mjs';
|
|
7
|
-
import { differenceInCalendarDays, addCalendarDaysToDate, moveDateToCalendarDay } from './chunk-DYW6WUHE.mjs';
|
|
8
|
-
import { flattenResourceTree } from './chunk-QR2SVYAD.mjs';
|
|
9
|
-
|
|
10
|
-
// src/controllers/month.controller.ts
|
|
11
|
-
var RESIZE_EDGE_SIZE = 12;
|
|
12
|
-
function detectResizeEdgeForAllDay(relativeX, elementWidth, threshold = RESIZE_EDGE_SIZE) {
|
|
13
|
-
if (relativeX <= threshold) return "start";
|
|
14
|
-
if (relativeX >= elementWidth - threshold) return "end";
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
function calculateDragClickOffset(eventStart, clickedDate, calendarOptions) {
|
|
18
|
-
return differenceInCalendarDays(eventStart, clickedDate, calendarOptions);
|
|
19
|
-
}
|
|
20
|
-
function processMonthDragMove(state, targetDate, dragClickDayOffset, mouseX, mouseY, calendarOptions) {
|
|
21
|
-
const result = {
|
|
22
|
-
dragGhostPosition: {
|
|
23
|
-
x: mouseX - state.offsetX,
|
|
24
|
-
y: mouseY - state.offsetY
|
|
25
|
-
},
|
|
26
|
-
dropTargetDate: targetDate,
|
|
27
|
-
delta: state.delta,
|
|
28
|
-
previewEvent: null,
|
|
29
|
-
shouldEmitDragStart: !state.isDragging && state.hasMovedMinDistance,
|
|
30
|
-
shouldEmitDrag: false
|
|
31
|
-
};
|
|
32
|
-
if (targetDate) {
|
|
33
|
-
const originalEvent = state.originalEvent;
|
|
34
|
-
const originalStart = typeof originalEvent.start === "string" ? new Date(originalEvent.start) : originalEvent.start;
|
|
35
|
-
const targetStartDate = addCalendarDaysToDate(targetDate, -dragClickDayOffset, calendarOptions);
|
|
36
|
-
const daysDelta = differenceInCalendarDays(originalStart, targetStartDate, calendarOptions);
|
|
37
|
-
result.delta = { days: daysDelta, milliseconds: 0 };
|
|
38
|
-
result.previewEvent = applyDeltaToEvent(originalEvent, result.delta, calendarOptions);
|
|
39
|
-
result.shouldEmitDrag = true;
|
|
40
|
-
}
|
|
41
|
-
return result;
|
|
42
|
-
}
|
|
43
|
-
function finalizeMonthDrag(state, context, calendarOptions) {
|
|
44
|
-
const { originalEvent, delta, isDragging } = state;
|
|
45
|
-
if (!isDragging || delta.days === 0) {
|
|
46
|
-
return {
|
|
47
|
-
success: false,
|
|
48
|
-
newEvent: null,
|
|
49
|
-
delta,
|
|
50
|
-
wasBlocked: false
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const newEvent = applyDeltaToEvent(originalEvent, delta, calendarOptions);
|
|
54
|
-
if (!context.eventOverlap) {
|
|
55
|
-
const overlapping = findOverlappingEvents(newEvent, context.parsedEvents);
|
|
56
|
-
if (overlapping.length > 0) {
|
|
57
|
-
return {
|
|
58
|
-
success: false,
|
|
59
|
-
newEvent: null,
|
|
60
|
-
delta,
|
|
61
|
-
wasBlocked: true
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
success: true,
|
|
67
|
-
newEvent,
|
|
68
|
-
delta,
|
|
69
|
-
wasBlocked: false
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function calculateResizeDeltas(originalEvent, targetDate, resizeEdge, calendarOptions) {
|
|
73
|
-
const originalStart = typeof originalEvent.start === "string" ? new Date(originalEvent.start) : originalEvent.start;
|
|
74
|
-
const originalEnd = originalEvent.end ? typeof originalEvent.end === "string" ? new Date(originalEvent.end) : originalEvent.end : new Date(originalStart);
|
|
75
|
-
let startDelta = 0;
|
|
76
|
-
let endDelta = 0;
|
|
77
|
-
if (resizeEdge === "start") {
|
|
78
|
-
const newStart = moveDateToCalendarDay(originalStart, targetDate, calendarOptions);
|
|
79
|
-
startDelta = newStart.getTime() - originalStart.getTime();
|
|
80
|
-
if (newStart > originalEnd) {
|
|
81
|
-
startDelta = originalEnd.getTime() - originalStart.getTime();
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
const newEnd = moveDateToCalendarDay(originalEnd, targetDate, calendarOptions);
|
|
85
|
-
endDelta = newEnd.getTime() - originalEnd.getTime();
|
|
86
|
-
if (newEnd < originalStart) {
|
|
87
|
-
endDelta = originalStart.getTime() - originalEnd.getTime();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return { startDelta, endDelta };
|
|
91
|
-
}
|
|
92
|
-
function calculateResizePreviewPosition(previewEvent, grid, originalRow) {
|
|
93
|
-
const previewStart = typeof previewEvent.start === "string" ? new Date(previewEvent.start) : previewEvent.start;
|
|
94
|
-
const previewEnd = previewEvent.end ? typeof previewEvent.end === "string" ? new Date(previewEvent.end) : previewEvent.end : previewStart;
|
|
95
|
-
const results = [];
|
|
96
|
-
for (let weekIndex = 0; weekIndex < grid.length; weekIndex++) {
|
|
97
|
-
const week = grid[weekIndex];
|
|
98
|
-
const weekStart = week[0].date;
|
|
99
|
-
const weekEnd = addDays(weekStart, 6);
|
|
100
|
-
weekEnd.setHours(23, 59, 59, 999);
|
|
101
|
-
if (previewStart <= weekEnd && previewEnd >= weekStart) {
|
|
102
|
-
let startCol = -1;
|
|
103
|
-
let endCol = 6;
|
|
104
|
-
for (let col = 0; col < 7; col++) {
|
|
105
|
-
const cellDate = week[col].date;
|
|
106
|
-
if (startCol === -1 && (isSameDay(cellDate, previewStart) || cellDate > previewStart)) {
|
|
107
|
-
startCol = col;
|
|
108
|
-
}
|
|
109
|
-
if (isSameDay(cellDate, previewEnd) || cellDate >= previewEnd) {
|
|
110
|
-
endCol = col;
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
if (previewStart < weekStart) startCol = 0;
|
|
115
|
-
if (startCol === -1) startCol = 0;
|
|
116
|
-
if (previewEnd > weekEnd) endCol = 6;
|
|
117
|
-
results.push({
|
|
118
|
-
weekIndex,
|
|
119
|
-
startCol,
|
|
120
|
-
endCol,
|
|
121
|
-
row: originalRow,
|
|
122
|
-
event: previewEvent
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return results;
|
|
127
|
-
}
|
|
128
|
-
function processMonthResizeMove(state, targetDate, grid, calendarOptions) {
|
|
129
|
-
const { startDelta, endDelta } = calculateResizeDeltas(state.originalEvent, targetDate, state.resizeEdge, calendarOptions);
|
|
130
|
-
const previewEvent = applyResizeToEvent(state.originalEvent, startDelta, endDelta);
|
|
131
|
-
const previewData = calculateResizePreviewPosition(previewEvent, grid, state.originalRow ?? 0);
|
|
132
|
-
return {
|
|
133
|
-
resizeTargetDate: targetDate,
|
|
134
|
-
startDelta,
|
|
135
|
-
endDelta,
|
|
136
|
-
previewEvent,
|
|
137
|
-
previewData
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
function finalizeMonthResize(state, context) {
|
|
141
|
-
const { originalEvent, startDelta, endDelta, isResizing } = state;
|
|
142
|
-
if (!isResizing || startDelta === 0 && endDelta === 0) {
|
|
143
|
-
return {
|
|
144
|
-
success: false,
|
|
145
|
-
newEvent: null,
|
|
146
|
-
wasBlocked: false
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
const newEvent = applyResizeToEvent(originalEvent, startDelta, endDelta);
|
|
150
|
-
if (!context.eventOverlap) {
|
|
151
|
-
const overlapping = findOverlappingEvents(newEvent, context.parsedEvents);
|
|
152
|
-
if (overlapping.length > 0) {
|
|
153
|
-
return {
|
|
154
|
-
success: false,
|
|
155
|
-
newEvent: null,
|
|
156
|
-
wasBlocked: true
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return {
|
|
161
|
-
success: true,
|
|
162
|
-
newEvent,
|
|
163
|
-
wasBlocked: false
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function findEventPositionInGrid(event, grid, getWeekEventPositions) {
|
|
167
|
-
for (let weekIndex = 0; weekIndex < grid.length; weekIndex++) {
|
|
168
|
-
const week = grid[weekIndex];
|
|
169
|
-
const positions = getWeekEventPositions(week);
|
|
170
|
-
for (const pos of positions) {
|
|
171
|
-
if (pos.event.id === event.id) {
|
|
172
|
-
return { weekIndex, startCol: pos.startCol, endCol: pos.endCol, row: pos.row };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
function getDragGhostStyle(position, dimensions, event) {
|
|
179
|
-
return {
|
|
180
|
-
position: "fixed",
|
|
181
|
-
left: `${position.x}px`,
|
|
182
|
-
top: `${position.y}px`,
|
|
183
|
-
width: dimensions ? `${dimensions.width}px` : "auto",
|
|
184
|
-
height: dimensions ? `${dimensions.height}px` : "auto",
|
|
185
|
-
...getSchedulerEventSurfaceStyle(event, {}),
|
|
186
|
-
background: "var(--p-scheduler-event-background)",
|
|
187
|
-
color: "var(--p-scheduler-event-color)",
|
|
188
|
-
padding: "0.25rem 0.5rem",
|
|
189
|
-
borderRadius: "var(--p-scheduler-event-border-radius)",
|
|
190
|
-
fontSize: "0.75rem",
|
|
191
|
-
fontWeight: "500",
|
|
192
|
-
lineHeight: "1.2",
|
|
193
|
-
pointerEvents: "none",
|
|
194
|
-
zIndex: "9999",
|
|
195
|
-
opacity: "0.9",
|
|
196
|
-
boxShadow: "var(--p-scheduler-event-shadow)",
|
|
197
|
-
whiteSpace: "nowrap",
|
|
198
|
-
overflow: "hidden",
|
|
199
|
-
textOverflow: "ellipsis",
|
|
200
|
-
display: "flex",
|
|
201
|
-
alignItems: "center",
|
|
202
|
-
boxSizing: "border-box"
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// src/controllers/timed.controller.ts
|
|
207
|
-
function resolveTimedPointerStart(input) {
|
|
208
|
-
if (!input.canDrag && !input.canResize) {
|
|
209
|
-
return { mode: "none" };
|
|
210
|
-
}
|
|
211
|
-
if (!input.rect) {
|
|
212
|
-
return { mode: "none" };
|
|
213
|
-
}
|
|
214
|
-
const rect = input.rect;
|
|
215
|
-
const relativeY = input.pointer.clientY - rect.top;
|
|
216
|
-
const resizeEdge = input.canResize ? detectResizeEdge(relativeY, 0, rect.height) : null;
|
|
217
|
-
if (resizeEdge) {
|
|
218
|
-
return {
|
|
219
|
-
mode: "resize",
|
|
220
|
-
resizeState: createResizeState(input.event, resizeEdge, input.pointer.clientY)
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
if (!input.canDrag) {
|
|
224
|
-
return { mode: "none" };
|
|
225
|
-
}
|
|
226
|
-
const offsetX = input.pointer.clientX - rect.left;
|
|
227
|
-
const offsetY = input.pointer.clientY - rect.top;
|
|
228
|
-
return {
|
|
229
|
-
mode: "drag",
|
|
230
|
-
dragState: createDragState(input.event, input.pointer.clientX, input.pointer.clientY, offsetX, offsetY)
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
function dispatchTimedPointerMove(hasDragState, hasResizeState, handlers, pointer) {
|
|
234
|
-
if (hasDragState) {
|
|
235
|
-
handlers.onDrag(pointer);
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (hasResizeState) {
|
|
239
|
-
handlers.onResize(pointer);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
function dispatchTimedPointerEnd(hasDragState, hasResizeState, handlers, pointer) {
|
|
243
|
-
if (hasDragState) {
|
|
244
|
-
handlers.onDrag(pointer);
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
if (hasResizeState) {
|
|
248
|
-
handlers.onResize(pointer);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
function calculateTimedDragDelta(state, columnWidth, slotHeight, slotDuration, snapDuration) {
|
|
252
|
-
const dxPixels = state.currentX - state.startX;
|
|
253
|
-
const dyPixels = state.currentY - state.startY;
|
|
254
|
-
const daysDelta = Math.round(dxPixels / columnWidth);
|
|
255
|
-
const minutesDelta = dyPixels / slotHeight * slotDuration;
|
|
256
|
-
const snappedMinutes = snapToSlot(minutesDelta, snapDuration);
|
|
257
|
-
const msDelta = snappedMinutes * 60 * 1e3;
|
|
258
|
-
return {
|
|
259
|
-
daysDelta,
|
|
260
|
-
millisecondsDelta: msDelta,
|
|
261
|
-
delta: { days: daysDelta, milliseconds: msDelta }
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
function findColumnIndexForDate(date, columns) {
|
|
265
|
-
return columns.findIndex((col) => {
|
|
266
|
-
const d1 = col.date;
|
|
267
|
-
return d1.getFullYear() === date.getFullYear() && d1.getMonth() === date.getMonth() && d1.getDate() === date.getDate();
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
function calculateTimedDragPreview(previewEvent, columns, slotMinTime, slotDuration, slotHeight) {
|
|
271
|
-
const previewStart = typeof previewEvent.start === "string" ? new Date(previewEvent.start) : previewEvent.start;
|
|
272
|
-
const previewColIndex = findColumnIndexForDate(previewStart, columns);
|
|
273
|
-
if (previewColIndex < 0 || previewColIndex >= columns.length) {
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
const previewEnd = previewEvent.end ? typeof previewEvent.end === "string" ? new Date(previewEvent.end) : previewEvent.end : new Date(previewStart.getTime() + 30 * 60 * 1e3);
|
|
277
|
-
const top = getYPositionFromTime(previewStart, slotMinTime, slotDuration, slotHeight);
|
|
278
|
-
const endY = getYPositionFromTime(previewEnd, slotMinTime, slotDuration, slotHeight);
|
|
279
|
-
const height = endY - top;
|
|
280
|
-
return {
|
|
281
|
-
colIndex: previewColIndex,
|
|
282
|
-
top,
|
|
283
|
-
height: Math.max(height, slotHeight / 2)
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
function processTimedDragMove(state, columnWidth, columns, context, snapDuration, calendarOptions) {
|
|
287
|
-
const { delta } = calculateTimedDragDelta(state, columnWidth, context.slotHeight, context.slotDuration, snapDuration);
|
|
288
|
-
const previewEvent = applyDeltaToEvent(state.originalEvent, delta, calendarOptions);
|
|
289
|
-
const preview = calculateTimedDragPreview(previewEvent, columns, context.slotMinTime, context.slotDuration, context.slotHeight);
|
|
290
|
-
if (!preview) {
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
return {
|
|
294
|
-
delta,
|
|
295
|
-
previewEvent,
|
|
296
|
-
previewColIndex: preview.colIndex,
|
|
297
|
-
previewTop: preview.top,
|
|
298
|
-
previewHeight: preview.height
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
function finalizeTimedDrag(state, context, calendarOptions) {
|
|
302
|
-
const { originalEvent, delta, isDragging } = state;
|
|
303
|
-
if (!isDragging || delta.days === 0 && delta.milliseconds === 0) {
|
|
304
|
-
return {
|
|
305
|
-
success: false,
|
|
306
|
-
newEvent: null,
|
|
307
|
-
delta,
|
|
308
|
-
wasBlocked: false
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
const newEvent = applyDeltaToEvent(originalEvent, delta, calendarOptions);
|
|
312
|
-
if (!context.eventOverlap) {
|
|
313
|
-
const overlapping = findOverlappingEvents(newEvent, context.parsedEvents);
|
|
314
|
-
if (overlapping.length > 0) {
|
|
315
|
-
return {
|
|
316
|
-
success: false,
|
|
317
|
-
newEvent: null,
|
|
318
|
-
delta,
|
|
319
|
-
wasBlocked: true
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
return {
|
|
324
|
-
success: true,
|
|
325
|
-
newEvent,
|
|
326
|
-
delta,
|
|
327
|
-
wasBlocked: false
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
function calculateTimedResizePreview(previewEvent, columns, slotMinTime, slotDuration, slotHeight) {
|
|
331
|
-
const previewStart = typeof previewEvent.start === "string" ? new Date(previewEvent.start) : previewEvent.start;
|
|
332
|
-
const previewColIndex = findColumnIndexForDate(previewStart, columns);
|
|
333
|
-
if (previewColIndex < 0) {
|
|
334
|
-
return null;
|
|
335
|
-
}
|
|
336
|
-
const previewEnd = previewEvent.end ? typeof previewEvent.end === "string" ? new Date(previewEvent.end) : previewEvent.end : new Date(previewStart.getTime() + 30 * 60 * 1e3);
|
|
337
|
-
const top = getYPositionFromTime(previewStart, slotMinTime, slotDuration, slotHeight);
|
|
338
|
-
const endY = getYPositionFromTime(previewEnd, slotMinTime, slotDuration, slotHeight);
|
|
339
|
-
const height = endY - top;
|
|
340
|
-
return {
|
|
341
|
-
colIndex: previewColIndex,
|
|
342
|
-
top,
|
|
343
|
-
height: Math.max(height, slotHeight / 2)
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
function processTimedResizeMove(state, columns, context) {
|
|
347
|
-
const { originalEvent, startDelta, endDelta } = state;
|
|
348
|
-
const previewEvent = applyResizeToEvent(originalEvent, startDelta, endDelta);
|
|
349
|
-
const preview = calculateTimedResizePreview(previewEvent, columns, context.slotMinTime, context.slotDuration, context.slotHeight);
|
|
350
|
-
if (!preview) {
|
|
351
|
-
return null;
|
|
352
|
-
}
|
|
353
|
-
return {
|
|
354
|
-
previewEvent,
|
|
355
|
-
previewColIndex: preview.colIndex,
|
|
356
|
-
previewTop: preview.top,
|
|
357
|
-
previewHeight: preview.height
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
function finalizeTimedResize(state, context) {
|
|
361
|
-
const { originalEvent, startDelta, endDelta, isResizing } = state;
|
|
362
|
-
if (!isResizing || startDelta === 0 && endDelta === 0) {
|
|
363
|
-
return {
|
|
364
|
-
success: false,
|
|
365
|
-
newEvent: null,
|
|
366
|
-
startDelta,
|
|
367
|
-
endDelta,
|
|
368
|
-
wasBlocked: false
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
const newEvent = applyResizeToEvent(originalEvent, startDelta, endDelta);
|
|
372
|
-
if (!context.eventOverlap) {
|
|
373
|
-
const overlapping = findOverlappingEvents(newEvent, context.parsedEvents);
|
|
374
|
-
if (overlapping.length > 0) {
|
|
375
|
-
return {
|
|
376
|
-
success: false,
|
|
377
|
-
newEvent: null,
|
|
378
|
-
startDelta,
|
|
379
|
-
endDelta,
|
|
380
|
-
wasBlocked: true
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return {
|
|
385
|
-
success: true,
|
|
386
|
-
newEvent,
|
|
387
|
-
startDelta,
|
|
388
|
-
endDelta,
|
|
389
|
-
wasBlocked: false
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
function getTimedPreviewStyle(top, height, event) {
|
|
393
|
-
return {
|
|
394
|
-
position: "absolute",
|
|
395
|
-
top: `${top}px`,
|
|
396
|
-
height: `${height}px`,
|
|
397
|
-
left: "var(--p-scheduler-timed-event-inset-inline-start, 2px)",
|
|
398
|
-
right: "var(--p-scheduler-timed-event-inset-inline-end, 4px)",
|
|
399
|
-
zIndex: "100",
|
|
400
|
-
pointerEvents: "none",
|
|
401
|
-
opacity: "0.7",
|
|
402
|
-
...getSchedulerEventSurfaceStyle(event, {}),
|
|
403
|
-
background: "var(--p-scheduler-event-background)",
|
|
404
|
-
borderColor: "var(--p-scheduler-event-border-color)",
|
|
405
|
-
color: "var(--p-scheduler-event-color)"
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
function hasTimedDropConstraints(eventConstraint, eventAllow, blockedIntervals) {
|
|
409
|
-
return Boolean(eventConstraint || eventAllow || blockedIntervals);
|
|
410
|
-
}
|
|
411
|
-
function toEventDate(value) {
|
|
412
|
-
if (!value) {
|
|
413
|
-
return null;
|
|
414
|
-
}
|
|
415
|
-
if (value instanceof Date) {
|
|
416
|
-
return new Date(value);
|
|
417
|
-
}
|
|
418
|
-
const parsed = new Date(value);
|
|
419
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
420
|
-
return null;
|
|
421
|
-
}
|
|
422
|
-
return parsed;
|
|
423
|
-
}
|
|
424
|
-
function canDropTimedPreviewEvent(input) {
|
|
425
|
-
if (!input.previewEvent || !input.originalEvent) {
|
|
426
|
-
return true;
|
|
427
|
-
}
|
|
428
|
-
const start = toEventDate(input.previewEvent.start);
|
|
429
|
-
if (!start) {
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
const end = toEventDate(input.previewEvent.end) ?? start;
|
|
433
|
-
const resourceId = input.resourceId ?? input.previewEvent.resourceId;
|
|
434
|
-
return canDropEvent(start, end, false, input.view, input.originalEvent, input.eventConstraint, input.eventAllow, input.businessHours, input.blockedIntervals, resourceId);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// src/controllers/timeline.controller.ts
|
|
438
|
-
function resolveTimelineSnapDuration(slotDuration, explicitSnapDuration) {
|
|
439
|
-
if (explicitSnapDuration !== void 0) return explicitSnapDuration;
|
|
440
|
-
if (slotDuration >= 60 && slotDuration % 30 === 0) return 30;
|
|
441
|
-
if (slotDuration >= 30 && slotDuration % 15 === 0) return 15;
|
|
442
|
-
return slotDuration;
|
|
443
|
-
}
|
|
444
|
-
var TIMELINE_RESIZE_EDGE_SIZE = 12;
|
|
445
|
-
function detectResizeEdgeForTimeline(relativeX, elementWidth, threshold = TIMELINE_RESIZE_EDGE_SIZE) {
|
|
446
|
-
if (relativeX <= threshold) return "start";
|
|
447
|
-
if (relativeX >= elementWidth - threshold) return "end";
|
|
448
|
-
return null;
|
|
449
|
-
}
|
|
450
|
-
function createTimelineDragState(event, startX, startY, offsetX, offsetY) {
|
|
451
|
-
return {
|
|
452
|
-
event: { ...event },
|
|
453
|
-
originalEvent: { ...event },
|
|
454
|
-
startX,
|
|
455
|
-
startY,
|
|
456
|
-
currentX: startX,
|
|
457
|
-
currentY: startY,
|
|
458
|
-
offsetX,
|
|
459
|
-
offsetY,
|
|
460
|
-
delta: { days: 0, milliseconds: 0 },
|
|
461
|
-
isDragging: false,
|
|
462
|
-
hasMovedMinDistance: false
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
function updateTimelineDragState(state, currentX, currentY, minDistance = DEFAULT_DRAG_MIN_DISTANCE) {
|
|
466
|
-
const dx = currentX - state.startX;
|
|
467
|
-
const dy = currentY - state.startY;
|
|
468
|
-
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
469
|
-
return {
|
|
470
|
-
...state,
|
|
471
|
-
currentX,
|
|
472
|
-
currentY,
|
|
473
|
-
hasMovedMinDistance: state.hasMovedMinDistance || distance >= minDistance,
|
|
474
|
-
isDragging: state.hasMovedMinDistance || distance >= minDistance
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
function calculateTimelineDragDelta(state, context) {
|
|
478
|
-
const { viewStart, viewEnd, totalWidth, slotDuration, snapDuration, minTimeMinutes, maxTimeMinutes } = context;
|
|
479
|
-
let totalDuration;
|
|
480
|
-
if (minTimeMinutes !== void 0 && maxTimeMinutes !== void 0) {
|
|
481
|
-
const businessMinutesPerDay = maxTimeMinutes - minTimeMinutes;
|
|
482
|
-
const dayCount = Math.ceil((viewEnd.getTime() - viewStart.getTime()) / (24 * 60 * 60 * 1e3));
|
|
483
|
-
totalDuration = dayCount * businessMinutesPerDay * 60 * 1e3;
|
|
484
|
-
} else {
|
|
485
|
-
totalDuration = viewEnd.getTime() - viewStart.getTime();
|
|
486
|
-
}
|
|
487
|
-
const dxPixels = state.currentX - state.startX;
|
|
488
|
-
const msPerPixel = totalDuration / totalWidth;
|
|
489
|
-
const rawTimeDelta = dxPixels * msPerPixel;
|
|
490
|
-
const slotMs = (snapDuration ?? slotDuration) * 60 * 1e3;
|
|
491
|
-
const snappedTimeDelta = Math.round(rawTimeDelta / slotMs) * slotMs;
|
|
492
|
-
return { days: 0, milliseconds: snappedTimeDelta };
|
|
493
|
-
}
|
|
494
|
-
function processTimelineDragMove(state, mouseX, mouseY, context, minDistance = DEFAULT_DRAG_MIN_DISTANCE) {
|
|
495
|
-
const updatedState = updateTimelineDragState(state, mouseX, mouseY, minDistance);
|
|
496
|
-
const delta = calculateTimelineDragDelta(updatedState, context);
|
|
497
|
-
const result = {
|
|
498
|
-
dragGhostPosition: {
|
|
499
|
-
x: mouseX - updatedState.offsetX,
|
|
500
|
-
y: mouseY - updatedState.offsetY
|
|
501
|
-
},
|
|
502
|
-
delta,
|
|
503
|
-
previewEvent: null,
|
|
504
|
-
shouldEmitDragStart: !state.isDragging && updatedState.hasMovedMinDistance,
|
|
505
|
-
shouldEmitDrag: false
|
|
506
|
-
};
|
|
507
|
-
if (updatedState.hasMovedMinDistance) {
|
|
508
|
-
result.previewEvent = applyDeltaToEvent(state.originalEvent, delta, context);
|
|
509
|
-
result.shouldEmitDrag = true;
|
|
510
|
-
}
|
|
511
|
-
return result;
|
|
512
|
-
}
|
|
513
|
-
function finalizeTimelineDrag(state, delta, context) {
|
|
514
|
-
const { originalEvent, isDragging } = state;
|
|
515
|
-
const hasTimeDelta = delta.days !== 0 || delta.milliseconds !== 0;
|
|
516
|
-
const hasResourceTargetDelta = context.targetResourceId !== void 0 && context.targetResourceId !== originalEvent.resourceId || context.targetResourceIds !== void 0 && (context.targetResourceIds.length !== (originalEvent.resourceIds?.length ?? 0) || context.targetResourceIds.some((resourceId, index) => resourceId !== originalEvent.resourceIds?.[index]));
|
|
517
|
-
if (!isDragging || !hasTimeDelta && !hasResourceTargetDelta) {
|
|
518
|
-
return { success: false, newEvent: null, delta, wasBlocked: false };
|
|
519
|
-
}
|
|
520
|
-
const newEvent = applyDeltaToEvent(originalEvent, delta, context);
|
|
521
|
-
if (context.overlapPolicy === "prevent" && context.allEvents) {
|
|
522
|
-
const candidateEvent = {
|
|
523
|
-
...newEvent,
|
|
524
|
-
resourceId: context.targetResourceId ?? newEvent.resourceId,
|
|
525
|
-
resourceIds: context.targetResourceIds ?? newEvent.resourceIds
|
|
526
|
-
};
|
|
527
|
-
if (hasOverlapInAnyAssignedResource(candidateEvent, context.allEvents)) {
|
|
528
|
-
return { success: false, newEvent: null, delta, wasBlocked: true };
|
|
529
|
-
}
|
|
530
|
-
} else if (!context.eventOverlap) {
|
|
531
|
-
const overlapping = findOverlappingEvents(newEvent, context.parsedEvents);
|
|
532
|
-
if (overlapping.length > 0) {
|
|
533
|
-
return { success: false, newEvent: null, delta, wasBlocked: true };
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
return { success: true, newEvent, delta, wasBlocked: false };
|
|
537
|
-
}
|
|
538
|
-
function createTimelineResizeState(event, edge, startX, startY) {
|
|
539
|
-
return {
|
|
540
|
-
event: { ...event },
|
|
541
|
-
originalEvent: { ...event },
|
|
542
|
-
edge,
|
|
543
|
-
startX,
|
|
544
|
-
currentX: startX,
|
|
545
|
-
startY,
|
|
546
|
-
currentY: startY,
|
|
547
|
-
startDelta: 0,
|
|
548
|
-
endDelta: 0,
|
|
549
|
-
visualStartPx: 0,
|
|
550
|
-
visualEndPx: 0,
|
|
551
|
-
isResizing: false
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
function calculateTimelineResizeDeltas(state, context) {
|
|
555
|
-
const { viewStart, viewEnd, totalWidth, slotDuration, snapDuration, minTimeMinutes, maxTimeMinutes } = context;
|
|
556
|
-
let totalDuration;
|
|
557
|
-
if (minTimeMinutes !== void 0 && maxTimeMinutes !== void 0) {
|
|
558
|
-
const businessMinutesPerDay = maxTimeMinutes - minTimeMinutes;
|
|
559
|
-
const dayCount = Math.ceil((viewEnd.getTime() - viewStart.getTime()) / (24 * 60 * 60 * 1e3));
|
|
560
|
-
totalDuration = dayCount * businessMinutesPerDay * 60 * 1e3;
|
|
561
|
-
} else {
|
|
562
|
-
totalDuration = viewEnd.getTime() - viewStart.getTime();
|
|
563
|
-
}
|
|
564
|
-
const dxPixels = state.currentX - state.startX;
|
|
565
|
-
const msPerPixel = totalDuration / totalWidth;
|
|
566
|
-
const rawTimeDelta = dxPixels * msPerPixel;
|
|
567
|
-
const snapMs = (snapDuration ?? slotDuration) * 60 * 1e3;
|
|
568
|
-
const snappedTimeDelta = Math.round(rawTimeDelta / snapMs) * snapMs;
|
|
569
|
-
const originalEvent = state.originalEvent;
|
|
570
|
-
const originalStart = typeof originalEvent.start === "string" ? new Date(originalEvent.start) : originalEvent.start;
|
|
571
|
-
const originalEnd = originalEvent.end ? typeof originalEvent.end === "string" ? new Date(originalEvent.end) : originalEvent.end : new Date(originalStart.getTime() + 60 * 60 * 1e3);
|
|
572
|
-
const preview = getSchedulerTimelineResizePreview({
|
|
573
|
-
edge: state.edge,
|
|
574
|
-
event: originalEvent,
|
|
575
|
-
start: originalStart,
|
|
576
|
-
end: originalEnd,
|
|
577
|
-
deltaMs: snappedTimeDelta,
|
|
578
|
-
snapMinutes: snapMs / 6e4
|
|
579
|
-
});
|
|
580
|
-
return { startDelta: preview.startDelta, endDelta: preview.endDelta };
|
|
581
|
-
}
|
|
582
|
-
function calculateBusinessTimeOffset(datetime, viewStart, minTimeMinutes, maxTimeMinutes) {
|
|
583
|
-
const msPerDay = 24 * 60 * 60 * 1e3;
|
|
584
|
-
const businessMinutesPerDay = maxTimeMinutes - minTimeMinutes;
|
|
585
|
-
const msPerBusinessDay = businessMinutesPerDay * 60 * 1e3;
|
|
586
|
-
const viewStartDay = new Date(viewStart);
|
|
587
|
-
viewStartDay.setHours(0, 0, 0, 0);
|
|
588
|
-
const targetDay = new Date(datetime);
|
|
589
|
-
targetDay.setHours(0, 0, 0, 0);
|
|
590
|
-
const daysDiff = Math.floor((targetDay.getTime() - viewStartDay.getTime()) / msPerDay);
|
|
591
|
-
const fullDaysOffset = daysDiff * msPerBusinessDay;
|
|
592
|
-
const timeMinutes = datetime.getHours() * 60 + datetime.getMinutes();
|
|
593
|
-
const clampedMinutes = Math.max(minTimeMinutes, Math.min(maxTimeMinutes, timeMinutes));
|
|
594
|
-
const minutesIntoBusinessDay = clampedMinutes - minTimeMinutes;
|
|
595
|
-
return fullDaysOffset + minutesIntoBusinessDay * 60 * 1e3;
|
|
596
|
-
}
|
|
597
|
-
function calculateResizePreviewStyle(originalEvent, startDelta, endDelta, context) {
|
|
598
|
-
const { viewStart, viewEnd, minTimeMinutes, maxTimeMinutes } = context;
|
|
599
|
-
const originalStart = typeof originalEvent.start === "string" ? new Date(originalEvent.start) : originalEvent.start;
|
|
600
|
-
const originalEnd = originalEvent.end ? typeof originalEvent.end === "string" ? new Date(originalEvent.end) : originalEvent.end : new Date(originalStart.getTime() + 60 * 60 * 1e3);
|
|
601
|
-
const newStart = new Date(originalStart.getTime() + startDelta);
|
|
602
|
-
const newEnd = new Date(originalEnd.getTime() + endDelta);
|
|
603
|
-
let leftPercent;
|
|
604
|
-
let widthPercent;
|
|
605
|
-
if (minTimeMinutes !== void 0 && maxTimeMinutes !== void 0) {
|
|
606
|
-
const businessMinutesPerDay = maxTimeMinutes - minTimeMinutes;
|
|
607
|
-
const dayCount = Math.ceil((viewEnd.getTime() - viewStart.getTime()) / (24 * 60 * 60 * 1e3));
|
|
608
|
-
const totalBusinessMs = dayCount * businessMinutesPerDay * 60 * 1e3;
|
|
609
|
-
const startOffset = calculateBusinessTimeOffset(newStart, viewStart, minTimeMinutes, maxTimeMinutes);
|
|
610
|
-
const endOffset = calculateBusinessTimeOffset(newEnd, viewStart, minTimeMinutes, maxTimeMinutes);
|
|
611
|
-
leftPercent = startOffset / totalBusinessMs * 100;
|
|
612
|
-
widthPercent = (endOffset - startOffset) / totalBusinessMs * 100;
|
|
613
|
-
} else {
|
|
614
|
-
const totalDuration = viewEnd.getTime() - viewStart.getTime();
|
|
615
|
-
leftPercent = (newStart.getTime() - viewStart.getTime()) / totalDuration * 100;
|
|
616
|
-
widthPercent = (newEnd.getTime() - newStart.getTime()) / totalDuration * 100;
|
|
617
|
-
}
|
|
618
|
-
return {
|
|
619
|
-
left: `calc(${leftPercent}% + 2px)`,
|
|
620
|
-
width: `calc(${Math.max(widthPercent, 1)}% - 4px)`
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
function processTimelineResizeMove(state, mouseX, context) {
|
|
624
|
-
const updatedState = {
|
|
625
|
-
...state,
|
|
626
|
-
currentX: mouseX,
|
|
627
|
-
isResizing: Math.abs(mouseX - state.startX) > 2
|
|
628
|
-
};
|
|
629
|
-
const { startDelta, endDelta } = calculateTimelineResizeDeltas(updatedState, context);
|
|
630
|
-
const previewEvent = applyResizeToEvent(state.originalEvent, startDelta, endDelta);
|
|
631
|
-
const previewStyle = calculateResizePreviewStyle(state.originalEvent, startDelta, endDelta, context);
|
|
632
|
-
return {
|
|
633
|
-
startDelta,
|
|
634
|
-
endDelta,
|
|
635
|
-
previewEvent,
|
|
636
|
-
previewStyle
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
function finalizeTimelineResize(state, startDelta, endDelta, context) {
|
|
640
|
-
const { originalEvent, isResizing } = state;
|
|
641
|
-
if (!isResizing || startDelta === 0 && endDelta === 0) {
|
|
642
|
-
return { success: false, newEvent: null, wasBlocked: false };
|
|
643
|
-
}
|
|
644
|
-
const newEvent = applyResizeToEvent(originalEvent, startDelta, endDelta);
|
|
645
|
-
if (context.overlapPolicy === "prevent" && context.allEvents) {
|
|
646
|
-
const candidateEvent = {
|
|
647
|
-
...newEvent,
|
|
648
|
-
resourceId: context.targetResourceId ?? newEvent.resourceId,
|
|
649
|
-
resourceIds: context.targetResourceIds ?? newEvent.resourceIds
|
|
650
|
-
};
|
|
651
|
-
if (hasOverlapInAnyAssignedResource(candidateEvent, context.allEvents)) {
|
|
652
|
-
return { success: false, newEvent: null, wasBlocked: true };
|
|
653
|
-
}
|
|
654
|
-
} else if (!context.eventOverlap) {
|
|
655
|
-
const overlapping = findOverlappingEvents(newEvent, context.parsedEvents);
|
|
656
|
-
if (overlapping.length > 0) {
|
|
657
|
-
return { success: false, newEvent: null, wasBlocked: true };
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
return { success: true, newEvent, wasBlocked: false };
|
|
661
|
-
}
|
|
662
|
-
function getTimelineDragGhostStyle(position, dimensions, event) {
|
|
663
|
-
return {
|
|
664
|
-
position: "fixed",
|
|
665
|
-
left: `${position.x}px`,
|
|
666
|
-
top: `${position.y}px`,
|
|
667
|
-
width: dimensions ? `${dimensions.width}px` : "auto",
|
|
668
|
-
height: dimensions ? `${dimensions.height}px` : "auto",
|
|
669
|
-
...getSchedulerEventSurfaceStyle(event, {}),
|
|
670
|
-
background: "var(--p-scheduler-event-background)",
|
|
671
|
-
color: "var(--p-scheduler-event-color)",
|
|
672
|
-
padding: "0.25rem 0.375rem",
|
|
673
|
-
borderRadius: "var(--p-scheduler-event-border-radius)",
|
|
674
|
-
borderInlineStart: "var(--p-scheduler-event-accent-width) solid var(--p-scheduler-event-border-accent)",
|
|
675
|
-
pointerEvents: "none",
|
|
676
|
-
zIndex: "9999",
|
|
677
|
-
opacity: "0.9",
|
|
678
|
-
boxShadow: "var(--p-scheduler-event-shadow)",
|
|
679
|
-
overflow: "hidden",
|
|
680
|
-
display: "flex",
|
|
681
|
-
flexDirection: "column",
|
|
682
|
-
justifyContent: "center",
|
|
683
|
-
alignItems: "flex-start",
|
|
684
|
-
gap: "0.125rem",
|
|
685
|
-
boxSizing: "border-box"
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// src/controllers/slot-tracking.controller.ts
|
|
690
|
-
var APPOINTMENT_SLOT_TIMED_VIEWS = /* @__PURE__ */ new Set(["day", "week", "resourceDay", "resourceWeek", "dateDay", "dateWeek"]);
|
|
691
|
-
var RESOURCE_SCOPED_SLOT_TRACKING_VIEWS = /* @__PURE__ */ new Set(["resourceDay", "resourceWeek", "dateDay", "dateWeek"]);
|
|
692
|
-
function createAppointmentSlotTrackingState() {
|
|
693
|
-
return {
|
|
694
|
-
initialized: false,
|
|
695
|
-
snapshots: /* @__PURE__ */ new Map(),
|
|
696
|
-
previousEvents: []
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
function isAppointmentSlotTrackingView(view) {
|
|
700
|
-
return APPOINTMENT_SLOT_TIMED_VIEWS.has(view);
|
|
701
|
-
}
|
|
702
|
-
function requiresResourceScopedSlotTracking(view) {
|
|
703
|
-
return RESOURCE_SCOPED_SLOT_TRACKING_VIEWS.has(view);
|
|
704
|
-
}
|
|
705
|
-
function getSlotTrackingKey(slot) {
|
|
706
|
-
const slotStart = slot.start instanceof Date ? slot.start : new Date(slot.start);
|
|
707
|
-
const slotEnd = slot.end instanceof Date ? slot.end : new Date(slot.end);
|
|
708
|
-
const resourceKey = slot.resourceId === void 0 ? "" : String(slot.resourceId);
|
|
709
|
-
return `${String(slot.id)}|${slotStart.getTime()}|${slotEnd.getTime()}|${resourceKey}`;
|
|
710
|
-
}
|
|
711
|
-
function cloneEventForSlotTracking(event) {
|
|
712
|
-
return {
|
|
713
|
-
...event,
|
|
714
|
-
start: event.start instanceof Date ? new Date(event.start) : event.start,
|
|
715
|
-
end: event.end instanceof Date ? new Date(event.end) : event.end,
|
|
716
|
-
resourceIds: event.resourceIds ? [...event.resourceIds] : event.resourceIds
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
function resolveEventDate(value) {
|
|
720
|
-
if (!value) return null;
|
|
721
|
-
const parsed = value instanceof Date ? new Date(value) : new Date(value);
|
|
722
|
-
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
723
|
-
}
|
|
724
|
-
function resolveEventRangeForSlotTracking(event) {
|
|
725
|
-
const start = resolveEventDate(event.start);
|
|
726
|
-
if (!start) return null;
|
|
727
|
-
const end = resolveEventDate(event.end);
|
|
728
|
-
if (end) {
|
|
729
|
-
return { start, end };
|
|
730
|
-
}
|
|
731
|
-
const durationMinutes = typeof event.duration === "number" && event.duration > 0 ? event.duration : 30;
|
|
732
|
-
return { start, end: new Date(start.getTime() + durationMinutes * 6e4) };
|
|
733
|
-
}
|
|
734
|
-
function getEventScheduleSignature(event) {
|
|
735
|
-
const range = resolveEventRangeForSlotTracking(event);
|
|
736
|
-
const resources = getEventResourceIds(event).map((id) => String(id)).sort().join(",");
|
|
737
|
-
const startKey = range ? range.start.getTime() : "invalid";
|
|
738
|
-
const endKey = range ? range.end.getTime() : "invalid";
|
|
739
|
-
return `${startKey}|${endKey}|${resources}`;
|
|
740
|
-
}
|
|
741
|
-
function doesEventOverlapSlot(event, slot) {
|
|
742
|
-
const range = resolveEventRangeForSlotTracking(event);
|
|
743
|
-
if (!range) return false;
|
|
744
|
-
const slotStart = slot.start instanceof Date ? slot.start : new Date(slot.start);
|
|
745
|
-
const slotEnd = slot.end instanceof Date ? slot.end : new Date(slot.end);
|
|
746
|
-
const overlaps = range.start < slotEnd && range.end > slotStart;
|
|
747
|
-
if (!overlaps) {
|
|
748
|
-
return false;
|
|
749
|
-
}
|
|
750
|
-
if (slot.resourceId === void 0) {
|
|
751
|
-
return true;
|
|
752
|
-
}
|
|
753
|
-
const eventResourceIds = getEventResourceIds(event);
|
|
754
|
-
return eventResourceIds.includes(slot.resourceId);
|
|
755
|
-
}
|
|
756
|
-
function resolveResourceScopes(context) {
|
|
757
|
-
if (!requiresResourceScopedSlotTracking(context.view)) {
|
|
758
|
-
return [void 0];
|
|
759
|
-
}
|
|
760
|
-
const leaves = flattenResourceTree(context.resources).filter((resource) => !resource.children || resource.children.length === 0);
|
|
761
|
-
return leaves.length > 0 ? leaves : [void 0];
|
|
762
|
-
}
|
|
763
|
-
function collectVisibleAppointmentSlots(context) {
|
|
764
|
-
const resourceScopes = resolveResourceScopes(context);
|
|
765
|
-
const slots = [];
|
|
766
|
-
for (const resource of resourceScopes) {
|
|
767
|
-
slots.push(...getSlotsForTimeRange(context.options, context.viewRange.start, context.viewRange.end, resource, context.slotMinTime, context.slotMaxTime));
|
|
768
|
-
}
|
|
769
|
-
return slots;
|
|
770
|
-
}
|
|
771
|
-
function buildSlotTrackingSnapshot(context, eventList) {
|
|
772
|
-
const slots = collectVisibleAppointmentSlots(context);
|
|
773
|
-
const updatedSlots = updateSlotsAvailability(slots, eventList);
|
|
774
|
-
const snapshot = /* @__PURE__ */ new Map();
|
|
775
|
-
for (const slot of updatedSlots) {
|
|
776
|
-
snapshot.set(getSlotTrackingKey(slot), {
|
|
777
|
-
slot,
|
|
778
|
-
bookedCount: slot.bookedCount ?? 0
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
return snapshot;
|
|
782
|
-
}
|
|
783
|
-
function findBookingCandidate(slot, currentEvents, previousEvents) {
|
|
784
|
-
const previousById = new Map(previousEvents.map((event) => [event.id, getEventScheduleSignature(event)]));
|
|
785
|
-
for (const event of currentEvents) {
|
|
786
|
-
const previousSignature = previousById.get(event.id);
|
|
787
|
-
const currentSignature = getEventScheduleSignature(event);
|
|
788
|
-
if (previousSignature === currentSignature) {
|
|
789
|
-
continue;
|
|
790
|
-
}
|
|
791
|
-
if (doesEventOverlapSlot(event, slot)) {
|
|
792
|
-
return event;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
return null;
|
|
796
|
-
}
|
|
797
|
-
function findCancellationCandidate(slot, currentEvents, previousEvents) {
|
|
798
|
-
const currentById = new Map(currentEvents.map((event) => [event.id, getEventScheduleSignature(event)]));
|
|
799
|
-
for (const event of previousEvents) {
|
|
800
|
-
const currentSignature = currentById.get(event.id);
|
|
801
|
-
const previousSignature = getEventScheduleSignature(event);
|
|
802
|
-
if (currentSignature === previousSignature) {
|
|
803
|
-
continue;
|
|
804
|
-
}
|
|
805
|
-
if (doesEventOverlapSlot(event, slot)) {
|
|
806
|
-
return event;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
return null;
|
|
810
|
-
}
|
|
811
|
-
function syncAppointmentSlotTracking(state, context, currentEvents) {
|
|
812
|
-
if (!context.options.enabled || !isAppointmentSlotTrackingView(context.view)) {
|
|
813
|
-
return {
|
|
814
|
-
state: createAppointmentSlotTrackingState(),
|
|
815
|
-
changes: []
|
|
816
|
-
};
|
|
817
|
-
}
|
|
818
|
-
const currentSnapshot = buildSlotTrackingSnapshot(context, currentEvents);
|
|
819
|
-
if (!state.initialized) {
|
|
820
|
-
return {
|
|
821
|
-
state: {
|
|
822
|
-
initialized: true,
|
|
823
|
-
snapshots: currentSnapshot,
|
|
824
|
-
previousEvents: currentEvents.map(cloneEventForSlotTracking)
|
|
825
|
-
},
|
|
826
|
-
changes: []
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
const changes = [];
|
|
830
|
-
const previousSnapshot = state.snapshots;
|
|
831
|
-
const previousEvents = state.previousEvents;
|
|
832
|
-
for (const [slotKey, currentState] of currentSnapshot.entries()) {
|
|
833
|
-
const previousState = previousSnapshot.get(slotKey);
|
|
834
|
-
const previousBookedCount = previousState?.bookedCount ?? 0;
|
|
835
|
-
const currentBookedCount = currentState.bookedCount;
|
|
836
|
-
if (currentBookedCount > previousBookedCount) {
|
|
837
|
-
const bookingEvent = findBookingCandidate(currentState.slot, currentEvents, previousEvents);
|
|
838
|
-
if (bookingEvent) {
|
|
839
|
-
changes.push({
|
|
840
|
-
type: "book",
|
|
841
|
-
slot: currentState.slot,
|
|
842
|
-
event: bookingEvent
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
} else if (currentBookedCount < previousBookedCount) {
|
|
846
|
-
const canceledEvent = findCancellationCandidate(currentState.slot, currentEvents, previousEvents);
|
|
847
|
-
if (canceledEvent) {
|
|
848
|
-
changes.push({
|
|
849
|
-
type: "cancel",
|
|
850
|
-
slot: currentState.slot,
|
|
851
|
-
event: canceledEvent
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
return {
|
|
857
|
-
state: {
|
|
858
|
-
initialized: true,
|
|
859
|
-
snapshots: currentSnapshot,
|
|
860
|
-
previousEvents: currentEvents.map(cloneEventForSlotTracking)
|
|
861
|
-
},
|
|
862
|
-
changes
|
|
863
|
-
};
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
export { RESIZE_EDGE_SIZE, TIMELINE_RESIZE_EDGE_SIZE, calculateDragClickOffset, calculateResizeDeltas, calculateResizePreviewPosition, calculateResizePreviewStyle, calculateTimedDragDelta, calculateTimedDragPreview, calculateTimedResizePreview, calculateTimelineDragDelta, calculateTimelineResizeDeltas, canDropTimedPreviewEvent, cloneEventForSlotTracking, createAppointmentSlotTrackingState, createTimelineDragState, createTimelineResizeState, detectResizeEdgeForAllDay, detectResizeEdgeForTimeline, dispatchTimedPointerEnd, dispatchTimedPointerMove, finalizeMonthDrag, finalizeMonthResize, finalizeTimedDrag, finalizeTimedResize, finalizeTimelineDrag, finalizeTimelineResize, findColumnIndexForDate, findEventPositionInGrid, getDragGhostStyle, getSlotTrackingKey, getTimedPreviewStyle, getTimelineDragGhostStyle, hasTimedDropConstraints, isAppointmentSlotTrackingView, processMonthDragMove, processMonthResizeMove, processTimedDragMove, processTimedResizeMove, processTimelineDragMove, processTimelineResizeMove, resolveTimedPointerStart, resolveTimelineSnapDuration, syncAppointmentSlotTracking, updateTimelineDragState };
|