@super-calendar/native 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1700 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ const require_MonthList = require("./MonthList-BCfN-UGz.js");
25
+ let date_fns = require("date-fns");
26
+ let react = require("react");
27
+ let react_native_reanimated = require("react-native-reanimated");
28
+ react_native_reanimated = __toESM(react_native_reanimated);
29
+ let _super_calendar_core = require("@super-calendar/core");
30
+ let _legendapp_list_react_native = require("@legendapp/list/react-native");
31
+ let react_native = require("react-native");
32
+ let react_jsx_runtime = require("react/jsx-runtime");
33
+ let react_native_gesture_handler = require("react-native-gesture-handler");
34
+ //#region src/components/Agenda.tsx
35
+ /**
36
+ * A vertical, day-grouped list of events (no time grid). Events are sorted by
37
+ * start, grouped under a date header per day. The consumer controls which
38
+ * events (and therefore which date range) are shown.
39
+ */
40
+ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLongPressEvent, onPressDay, activeDate, itemSeparatorComponent }) {
41
+ const theme = require_MonthList.useCalendarTheme();
42
+ const RenderEventComponent = renderEvent;
43
+ const rows = (0, react.useMemo)(() => {
44
+ const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
45
+ const out = [];
46
+ let currentDay = null;
47
+ sorted.forEach((event, index) => {
48
+ if (!currentDay || !(0, date_fns.isSameDay)(event.start, currentDay)) {
49
+ currentDay = (0, date_fns.startOfDay)(event.start);
50
+ out.push({
51
+ kind: "header",
52
+ date: currentDay,
53
+ key: `h-${currentDay.toISOString()}`
54
+ });
55
+ }
56
+ out.push({
57
+ kind: "event",
58
+ event,
59
+ index,
60
+ key: `e-${keyExtractor(event, index)}`
61
+ });
62
+ });
63
+ return out;
64
+ }, [events, keyExtractor]);
65
+ const keyExtractorRow = (0, react.useCallback)((row) => row.key, []);
66
+ const renderItem = (0, react.useCallback)(({ item }) => {
67
+ if (item.kind === "header") {
68
+ const isHighlighted = activeDate ? (0, date_fns.isSameDay)(item.date, activeDate) : (0, _super_calendar_core.getIsToday)(item.date);
69
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
70
+ style: [styles$3.header, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }],
71
+ onPress: onPressDay ? () => onPressDay(item.date) : void 0,
72
+ accessibilityRole: onPressDay ? "button" : "header",
73
+ children: (0, date_fns.format)(item.date, "EEEE, d LLLL", { locale })
74
+ });
75
+ }
76
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
77
+ style: styles$3.eventRow,
78
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
79
+ event: item.event,
80
+ mode: "schedule",
81
+ isAllDay: (0, _super_calendar_core.isAllDayEvent)(item.event),
82
+ onPress: () => onPressEvent(item.event),
83
+ onLongPress: onLongPressEvent ? () => onLongPressEvent(item.event) : void 0
84
+ })
85
+ });
86
+ }, [
87
+ theme,
88
+ locale,
89
+ activeDate,
90
+ onPressDay,
91
+ onPressEvent,
92
+ onLongPressEvent,
93
+ RenderEventComponent
94
+ ]);
95
+ if (rows.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
96
+ style: [styles$3.empty, { color: theme.colors.textMuted }],
97
+ children: "No events"
98
+ });
99
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
100
+ style: styles$3.list,
101
+ data: rows,
102
+ keyExtractor: keyExtractorRow,
103
+ renderItem,
104
+ ItemSeparatorComponent: itemSeparatorComponent ?? void 0,
105
+ recycleItems: false
106
+ });
107
+ }
108
+ const styles$3 = react_native.StyleSheet.create({
109
+ list: { flex: 1 },
110
+ header: {
111
+ fontSize: 13,
112
+ fontWeight: "600",
113
+ paddingTop: 12,
114
+ paddingBottom: 4,
115
+ paddingHorizontal: 12
116
+ },
117
+ eventRow: {
118
+ paddingHorizontal: 12,
119
+ paddingVertical: 2
120
+ },
121
+ empty: {
122
+ fontSize: 14,
123
+ paddingVertical: 16,
124
+ paddingHorizontal: 12
125
+ }
126
+ });
127
+ //#endregion
128
+ //#region src/components/DefaultEvent.tsx
129
+ const BOX_PADDING_V = 2;
130
+ const TIME_LINE_HEIGHT = 30;
131
+ const FALLBACK_TITLE_LINE_HEIGHT = 16;
132
+ const numericStyle = (value, fallback) => typeof value === "number" ? value : fallback;
133
+ /**
134
+ * The built-in event renderer: a filled, rounded box showing the event title
135
+ * and (on the day/week grid, when the box is tall enough) its time range. The
136
+ * title fills the box in whole lines, never a half-cut last line, and clips
137
+ * without an ellipsis unless `ellipsizeTitle` is set. The time is secondary: it
138
+ * only shows once a full line is free beneath the title. Pass your own
139
+ * `renderEvent` to `<Calendar>` to replace it entirely.
140
+ */
141
+ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, cellStyle, onPress, onLongPress }) {
142
+ const theme = require_MonthList.useCalendarTheme();
143
+ const isAllDayEvent = isAllDay ?? false;
144
+ const timeLabel = (0, _super_calendar_core.eventTimeLabel)({
145
+ mode,
146
+ isAllDay: isAllDayEvent,
147
+ start: event.start,
148
+ end: event.end,
149
+ ampm,
150
+ showTime,
151
+ allDayLabel
152
+ });
153
+ const ellipsizeMode = (0, _super_calendar_core.titleEllipsizeMode)(ellipsizeTitle);
154
+ const titleLineHeight = numericStyle(theme.text.eventTitle.lineHeight, FALLBACK_TITLE_LINE_HEIGHT);
155
+ const accessibilityLabel = (0, _super_calendar_core.eventAccessibilityLabel)({
156
+ title: event.title,
157
+ isAllDay: isAllDayEvent,
158
+ start: event.start,
159
+ end: event.end,
160
+ ampm,
161
+ allDayLabel
162
+ });
163
+ const fixedTitleLines = (0, _super_calendar_core.titleNumberOfLines)(mode, isAllDayEvent);
164
+ const isSchedule = mode === "schedule";
165
+ const layout = (0, react_native_reanimated.useDerivedValue)(() => (0, _super_calendar_core.eventChipLayout)({
166
+ boxHeightPx: boxHeight?.value,
167
+ mode,
168
+ hasTime: timeLabel != null,
169
+ titleLineHeightPx: titleLineHeight,
170
+ timeLineHeightPx: TIME_LINE_HEIGHT,
171
+ paddingYPx: BOX_PADDING_V
172
+ }), [
173
+ boxHeight,
174
+ mode,
175
+ timeLabel,
176
+ titleLineHeight
177
+ ]);
178
+ const titleClipStyle = (0, react_native_reanimated.useAnimatedStyle)(() => {
179
+ const lines = layout.value.titleMaxLines;
180
+ return { maxHeight: lines > 0 ? lines * titleLineHeight : void 0 };
181
+ }, [layout, titleLineHeight]);
182
+ const timeStyle = (0, react_native_reanimated.useAnimatedStyle)(() => {
183
+ return { display: layout.value.showTime ? "flex" : "none" };
184
+ }, [layout]);
185
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.TouchableOpacity, {
186
+ style: [
187
+ styles$2.box,
188
+ isSchedule && styles$2.scheduleBox,
189
+ { backgroundColor: theme.colors.eventBackground },
190
+ event.disabled && styles$2.disabled,
191
+ cellStyle
192
+ ],
193
+ onPress,
194
+ onLongPress,
195
+ activeOpacity: .7,
196
+ accessibilityRole: "button",
197
+ accessibilityLabel,
198
+ accessibilityState: { disabled: event.disabled ?? false },
199
+ children: [event.title ? fixedTitleLines == null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
200
+ style: [styles$2.titleClip, titleClipStyle],
201
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
202
+ style: [
203
+ theme.text.eventTitle,
204
+ isSchedule && styles$2.scheduleTitle,
205
+ { color: theme.colors.eventText }
206
+ ],
207
+ ellipsizeMode,
208
+ allowFontScaling: false,
209
+ children: event.title
210
+ })
211
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
212
+ style: [
213
+ theme.text.eventTitle,
214
+ styles$2.title,
215
+ isSchedule && styles$2.scheduleTitle,
216
+ { color: theme.colors.eventText }
217
+ ],
218
+ numberOfLines: fixedTitleLines,
219
+ ellipsizeMode,
220
+ allowFontScaling: false,
221
+ children: event.title
222
+ }) : null, timeLabel ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
223
+ style: timeStyle,
224
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
225
+ style: [
226
+ styles$2.time,
227
+ isSchedule && styles$2.scheduleTime,
228
+ { color: theme.colors.eventText }
229
+ ],
230
+ numberOfLines: 2,
231
+ ellipsizeMode,
232
+ allowFontScaling: false,
233
+ children: timeLabel
234
+ })
235
+ }) : null]
236
+ });
237
+ }
238
+ const styles$2 = react_native.StyleSheet.create({
239
+ box: {
240
+ flexGrow: 1,
241
+ flexShrink: 1,
242
+ flexBasis: "auto",
243
+ borderRadius: 6,
244
+ paddingVertical: BOX_PADDING_V,
245
+ paddingHorizontal: 4,
246
+ overflow: "hidden"
247
+ },
248
+ scheduleBox: {
249
+ borderRadius: 8,
250
+ paddingVertical: 6,
251
+ paddingHorizontal: 10
252
+ },
253
+ scheduleTitle: {
254
+ fontSize: 14,
255
+ fontWeight: "600",
256
+ lineHeight: 18
257
+ },
258
+ scheduleTime: {
259
+ fontSize: 13,
260
+ lineHeight: 18,
261
+ opacity: .75
262
+ },
263
+ titleClip: { overflow: "hidden" },
264
+ title: { flexShrink: 1 },
265
+ time: {
266
+ fontSize: 11,
267
+ lineHeight: 15
268
+ },
269
+ disabled: { opacity: .5 }
270
+ });
271
+ //#endregion
272
+ //#region src/utils/useWebGridZoom.ts
273
+ const ZOOM_SENSITIVITY = .002;
274
+ /**
275
+ * Web-only: zoom the time grid with Ctrl/Cmd + scroll, standing in for the pinch
276
+ * gesture that web has no equivalent of. `target` is the grid's host node — on
277
+ * web a React Native View ref resolves to its DOM element. No-op off web, when
278
+ * `enabled` is false, or before the node mounts. Plain scroll is left untouched.
279
+ */
280
+ function useWebGridZoom(enabled, target, cellHeight, committedCellHeight, minHeight, maxHeight) {
281
+ (0, react.useEffect)(() => {
282
+ if (react_native.Platform.OS !== "web" || !enabled) return;
283
+ const node = target.current;
284
+ if (!node) return;
285
+ const handler = (event) => {
286
+ if (!event.ctrlKey && !event.metaKey) return;
287
+ event.preventDefault();
288
+ const next = Math.min(maxHeight, Math.max(minHeight, cellHeight.value * Math.exp(-event.deltaY * ZOOM_SENSITIVITY)));
289
+ cellHeight.value = next;
290
+ committedCellHeight.value = next;
291
+ };
292
+ node.addEventListener("wheel", handler, { passive: false });
293
+ return () => node.removeEventListener("wheel", handler);
294
+ }, [
295
+ enabled,
296
+ target,
297
+ cellHeight,
298
+ committedCellHeight,
299
+ minHeight,
300
+ maxHeight
301
+ ]);
302
+ }
303
+ //#endregion
304
+ //#region src/components/AllDayLane.tsx
305
+ /**
306
+ * The all-day lane that sits above the scrolling time grid. All-day events are
307
+ * excluded from the timed columns (see `layoutDayEvents`) and shown here,
308
+ * stacked under their day(s). Renders nothing when no day has an all-day event,
309
+ * so timed-only calendars are unaffected.
310
+ */
311
+ function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent, keyExtractor, onPressEvent, onLongPressEvent }) {
312
+ const theme = require_MonthList.useCalendarTheme();
313
+ const RenderEventComponent = renderEvent;
314
+ const allDay = events.filter(_super_calendar_core.isAllDayEvent);
315
+ const perDay = days.map((day) => {
316
+ const start = (0, date_fns.startOfDay)(day);
317
+ const next = (0, date_fns.addDays)(start, 1);
318
+ return allDay.filter((event) => event.start < next && event.end > start);
319
+ });
320
+ if (perDay.every((list) => list.length === 0)) return null;
321
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
322
+ style: [styles$1.lane, { borderBottomColor: theme.colors.gridLine }],
323
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
324
+ style: [styles$1.gutter, { width: hourColumnWidth }],
325
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
326
+ style: [styles$1.label, { color: theme.colors.textMuted }],
327
+ allowFontScaling: false,
328
+ children: "all-day"
329
+ })
330
+ }), days.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
331
+ style: [styles$1.column, { width: dayWidth }],
332
+ children: perDay[dayIndex].map((event, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
333
+ style: styles$1.chip,
334
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
335
+ event,
336
+ mode,
337
+ isAllDay: true,
338
+ onPress: () => onPressEvent(event),
339
+ onLongPress: onLongPressEvent ? () => onLongPressEvent(event) : void 0
340
+ })
341
+ }, keyExtractor(event, index)))
342
+ }, day.toISOString()))]
343
+ });
344
+ }
345
+ const styles$1 = react_native.StyleSheet.create({
346
+ lane: {
347
+ flexDirection: "row",
348
+ borderBottomWidth: react_native.StyleSheet.hairlineWidth
349
+ },
350
+ gutter: { justifyContent: "center" },
351
+ label: {
352
+ fontSize: 10,
353
+ textAlign: "right",
354
+ paddingRight: 6
355
+ },
356
+ column: {
357
+ paddingVertical: 2,
358
+ paddingHorizontal: 1,
359
+ gap: 2
360
+ },
361
+ chip: { minHeight: 18 }
362
+ });
363
+ //#endregion
364
+ //#region src/components/TimeGrid.tsx
365
+ const isWeb = react_native.Platform.OS === "web";
366
+ const MINUTES_PER_HOUR = 60;
367
+ const HOURS_PER_DAY = 24;
368
+ const MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
369
+ const PAGE_WINDOW = 180;
370
+ const PAGE_VIEWABILITY = { itemVisiblePercentThreshold: 90 };
371
+ const DEFAULT_HOUR_HEIGHT = 48;
372
+ const DEFAULT_MIN_HOUR_HEIGHT = 32;
373
+ const DEFAULT_MAX_HOUR_HEIGHT = 160;
374
+ const DEFAULT_HOUR_COLUMN_WIDTH = 56;
375
+ const MIN_EVENT_HEIGHT = 32;
376
+ const EVENT_GAP = 2;
377
+ const DRAG_ACTIVATE_MS = 300;
378
+ const MOVE_ACTIVATE_MS = 500;
379
+ const DRAG_ACTIVATE_PX = 8;
380
+ const RESIZE_HANDLE_HEIGHT = 14;
381
+ const DEFAULT_DRAG_STEP_MINUTES = 15;
382
+ const HOUR_LABEL_TOP_INSET = 12;
383
+ const NOW_TICK_MS = 6e4;
384
+ function useNow(enabled) {
385
+ const [now, setNow] = (0, react.useState)(() => /* @__PURE__ */ new Date());
386
+ (0, react.useEffect)(() => {
387
+ if (!enabled) return;
388
+ setNow(/* @__PURE__ */ new Date());
389
+ const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), NOW_TICK_MS);
390
+ return () => clearInterval(id);
391
+ }, [enabled]);
392
+ return now;
393
+ }
394
+ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWidth, dayIndex, dayCount, mode, renderEvent, snapMinutes, onPress, onLongPress, onDragEvent, onDragStart, showDragHandle }) {
395
+ const RenderEventComponent = renderEvent;
396
+ const theme = require_MonthList.useCalendarTheme();
397
+ const draggable = onDragEvent != null && !positioned.event.disabled;
398
+ const resizable = draggable && !positioned.continuesAfter;
399
+ const moveOffset = (0, react_native_reanimated.useSharedValue)(0);
400
+ const moveOffsetX = (0, react_native_reanimated.useSharedValue)(0);
401
+ const resizeDelta = (0, react_native_reanimated.useSharedValue)(0);
402
+ const boxHeight = (0, react_native_reanimated.useDerivedValue)(() => Math.max(positioned.durationHours * cellHeight.value + resizeDelta.value, MIN_EVENT_HEIGHT), [positioned.durationHours]);
403
+ const boxStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
404
+ top: (positioned.startHours - minHour) * cellHeight.value + moveOffset.value,
405
+ height: boxHeight.value,
406
+ transform: [{ translateX: moveOffsetX.value }]
407
+ }), [
408
+ positioned.startHours,
409
+ positioned.durationHours,
410
+ minHour
411
+ ]);
412
+ (0, react.useEffect)(() => {
413
+ moveOffset.value = 0;
414
+ moveOffsetX.value = 0;
415
+ resizeDelta.value = 0;
416
+ }, [
417
+ positioned.startHours,
418
+ positioned.durationHours,
419
+ moveOffset,
420
+ moveOffsetX,
421
+ resizeDelta
422
+ ]);
423
+ const latest = (0, react.useRef)({
424
+ event: positioned.event,
425
+ onDragEvent,
426
+ onDragStart
427
+ });
428
+ latest.current = {
429
+ event: positioned.event,
430
+ onDragEvent,
431
+ onDragStart
432
+ };
433
+ const snapBack = (0, react.useCallback)(() => {
434
+ moveOffset.value = 0;
435
+ moveOffsetX.value = 0;
436
+ resizeDelta.value = 0;
437
+ }, [
438
+ moveOffset,
439
+ moveOffsetX,
440
+ resizeDelta
441
+ ]);
442
+ const commitDrag = (0, react.useCallback)((deltaStartMin, deltaEndMin) => {
443
+ const { event, onDragEvent: handler } = latest.current;
444
+ if (!handler) return;
445
+ const next = (0, _super_calendar_core.resolveDraggedBounds)(event.start, event.end, deltaStartMin, deltaEndMin, snapMinutes);
446
+ if (!next) {
447
+ snapBack();
448
+ return;
449
+ }
450
+ if (handler(event, next.start, next.end) === false) snapBack();
451
+ }, [snapMinutes, snapBack]);
452
+ const notifyDragStart = (0, react.useCallback)(() => {
453
+ latest.current.onDragStart?.(latest.current.event);
454
+ }, []);
455
+ const moveGesture = (0, react.useMemo)(() => {
456
+ const pan = react_native_gesture_handler.Gesture.Pan().enabled(draggable).onStart(() => {
457
+ (0, react_native_reanimated.runOnJS)(notifyDragStart)();
458
+ }).onUpdate((event) => {
459
+ moveOffset.value = event.translationY;
460
+ moveOffsetX.value = event.translationX;
461
+ }).onEnd((event) => {
462
+ const minuteDelta = (0, _super_calendar_core.snapDeltaMinutes)(event.translationY, cellHeight.value, snapMinutes);
463
+ const rawDayDelta = dayWidth > 0 ? Math.round(event.translationX / dayWidth) : 0;
464
+ const dayDelta = Math.min(Math.max(dayIndex + rawDayDelta, 0), dayCount - 1) - dayIndex;
465
+ if (minuteDelta === 0 && dayDelta === 0) {
466
+ moveOffset.value = 0;
467
+ moveOffsetX.value = 0;
468
+ return;
469
+ }
470
+ moveOffset.value = minuteDelta / MINUTES_PER_HOUR * cellHeight.value;
471
+ moveOffsetX.value = dayDelta * dayWidth;
472
+ const totalDelta = minuteDelta + dayDelta * MINUTES_PER_DAY;
473
+ (0, react_native_reanimated.runOnJS)(commitDrag)(totalDelta, totalDelta);
474
+ });
475
+ return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS);
476
+ }, [
477
+ draggable,
478
+ snapMinutes,
479
+ cellHeight,
480
+ moveOffset,
481
+ moveOffsetX,
482
+ dayWidth,
483
+ dayIndex,
484
+ dayCount,
485
+ commitDrag,
486
+ notifyDragStart
487
+ ]);
488
+ const resizeGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(resizable).onStart(() => {
489
+ (0, react_native_reanimated.runOnJS)(notifyDragStart)();
490
+ }).onUpdate((event) => {
491
+ resizeDelta.value = event.translationY;
492
+ }).onEnd((event) => {
493
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(event.translationY, cellHeight.value, snapMinutes);
494
+ if (delta === 0) {
495
+ resizeDelta.value = 0;
496
+ return;
497
+ }
498
+ resizeDelta.value = delta / MINUTES_PER_HOUR * cellHeight.value;
499
+ (0, react_native_reanimated.runOnJS)(commitDrag)(0, delta);
500
+ }), [
501
+ resizable,
502
+ snapMinutes,
503
+ cellHeight,
504
+ resizeDelta,
505
+ commitDrag,
506
+ notifyDragStart
507
+ ]);
508
+ const handlePress = () => onPress(positioned.event);
509
+ const handleLongPress = !draggable && onLongPress ? () => onLongPress(positioned.event) : void 0;
510
+ const box = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
511
+ style: [
512
+ styles.eventBox,
513
+ {
514
+ left,
515
+ width
516
+ },
517
+ boxStyle
518
+ ],
519
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
520
+ event: positioned.event,
521
+ mode,
522
+ boxHeight,
523
+ continuesBefore: positioned.continuesBefore,
524
+ continuesAfter: positioned.continuesAfter,
525
+ onPress: handlePress,
526
+ onLongPress: handleLongPress
527
+ }), resizable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
528
+ gesture: resizeGesture,
529
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
530
+ style: styles.resizeHandle,
531
+ children: showDragHandle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles.resizeGrip, { backgroundColor: theme.colors.eventText }] }) : null
532
+ })
533
+ }) : null]
534
+ });
535
+ if (!draggable) return box;
536
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
537
+ gesture: moveGesture,
538
+ children: box
539
+ });
540
+ }
541
+ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hourComponent }) => {
542
+ const theme = require_MonthList.useCalendarTheme();
543
+ const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (hour - minHour) * cellHeight.value }), [hour, minHour]);
544
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
545
+ style: [
546
+ styles.hourRow,
547
+ styles.nonInteractive,
548
+ animatedStyle
549
+ ],
550
+ children: [hourComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
551
+ style: { width: hourColumnWidth },
552
+ children: hourComponent(hour, ampm)
553
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
554
+ style: [
555
+ theme.text.hourLabel,
556
+ styles.hourLabel,
557
+ {
558
+ width: hourColumnWidth,
559
+ color: theme.colors.textMuted
560
+ }
561
+ ],
562
+ allowFontScaling: false,
563
+ children: label
564
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles.hourLine, { backgroundColor: theme.colors.gridLine }] })]
565
+ });
566
+ };
567
+ const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth }) => {
568
+ const theme = require_MonthList.useCalendarTheme();
569
+ const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (hour - minHour + fraction) * cellHeight.value }), [
570
+ hour,
571
+ minHour,
572
+ fraction
573
+ ]);
574
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
575
+ styles.timeslotLine,
576
+ styles.nonInteractive,
577
+ {
578
+ left: hourColumnWidth,
579
+ backgroundColor: theme.colors.gridLine
580
+ },
581
+ animatedStyle
582
+ ] });
583
+ };
584
+ const NowIndicator = ({ cellHeight, nowHours, minHour, left, width, color }) => {
585
+ const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (nowHours - minHour) * cellHeight.value }), [nowHours, minHour]);
586
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
587
+ styles.nowIndicator,
588
+ styles.nonInteractive,
589
+ {
590
+ left,
591
+ width,
592
+ backgroundColor: color
593
+ },
594
+ animatedStyle
595
+ ] });
596
+ };
597
+ const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color }) => {
598
+ const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
599
+ top: (startHour - minHour) * cellHeight.value,
600
+ height: (endHour - startHour) * cellHeight.value
601
+ }), [
602
+ startHour,
603
+ endHour,
604
+ minHour
605
+ ]);
606
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
607
+ testID: "business-hours-shade",
608
+ style: [
609
+ styles.shadeBand,
610
+ styles.nonInteractive,
611
+ {
612
+ left,
613
+ width,
614
+ backgroundColor: color
615
+ },
616
+ animatedStyle
617
+ ]
618
+ });
619
+ };
620
+ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hourHeight, committedCellHeight, scrollY, isActive, initialScrollY, onSettleOffset, weekStartsOn, weekEndsOn, width, hourColumnWidth, minHour, maxHour, ampm, timeslots, isRTL, showAllDayEventCell, showVerticalScrollIndicator, verticalScrollEnabled, hourComponent, calendarCellStyle, minHourHeight, maxHourHeight, showNowIndicator, businessHours, renderEvent, keyExtractor, snapMinutes, showDragHandle, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, onPressCell, onLongPressCell, onCreateEvent }) {
621
+ const theme = require_MonthList.useCalendarTheme();
622
+ const scrollRef = (0, react_native_reanimated.useAnimatedRef)();
623
+ const heightSource = isActive ? cellHeight : committedCellHeight;
624
+ const isDragging = (0, react_native_reanimated.useSharedValue)(false);
625
+ const isActiveShared = (0, react_native_reanimated.useSharedValue)(isActive);
626
+ (0, react.useEffect)(() => {
627
+ isActiveShared.value = isActive;
628
+ }, [isActive, isActiveShared]);
629
+ const scrollHandler = (0, react_native_reanimated.useAnimatedScrollHandler)({
630
+ onScroll: (event) => {
631
+ if (isActiveShared.value && isDragging.value) scrollY.value = event.contentOffset.y;
632
+ },
633
+ onBeginDrag: () => {
634
+ isDragging.value = true;
635
+ },
636
+ onEndDrag: (event) => {
637
+ isDragging.value = false;
638
+ if (!isWeb && isActiveShared.value) {
639
+ scrollY.value = event.contentOffset.y;
640
+ (0, react_native_reanimated.runOnJS)(onSettleOffset)(event.contentOffset.y);
641
+ }
642
+ },
643
+ onMomentumEnd: (event) => {
644
+ isDragging.value = false;
645
+ if (!isWeb && isActiveShared.value) {
646
+ scrollY.value = event.contentOffset.y;
647
+ (0, react_native_reanimated.runOnJS)(onSettleOffset)(event.contentOffset.y);
648
+ }
649
+ }
650
+ });
651
+ (0, react_native_reanimated.useAnimatedReaction)(() => scrollY.value, (current, previous) => {
652
+ if (!isActiveShared.value && current !== previous) (0, react_native_reanimated.scrollTo)(scrollRef, 0, current, false);
653
+ });
654
+ (0, react_native_reanimated.useAnimatedReaction)(() => isActiveShared.value, (active, previous) => {
655
+ if (isWeb || !active || active === previous) return;
656
+ (0, react_native_reanimated.scrollTo)(scrollRef, 0, scrollY.value, false);
657
+ });
658
+ const days = (0, react.useMemo)(() => (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, isRTL, weekEndsOn), [
659
+ mode,
660
+ date,
661
+ weekStartsOn,
662
+ numberOfDays,
663
+ isRTL,
664
+ weekEndsOn
665
+ ]);
666
+ const dayWidth = (width - hourColumnWidth) / days.length;
667
+ const dayLeft = (dayIndex) => hourColumnWidth + dayIndex * dayWidth;
668
+ const dayLayouts = (0, react.useMemo)(() => days.map((day) => (0, _super_calendar_core.layoutDayEvents)(events, day)), [days, events]);
669
+ const cellDateFromTouch = (event) => {
670
+ const { locationX, locationY } = event.nativeEvent;
671
+ const day = days[days.length === 1 ? 0 : Math.floor(locationX / dayWidth)];
672
+ if (!day) return null;
673
+ const minutes = Math.round((minHour + locationY / heightSource.value) * MINUTES_PER_HOUR);
674
+ const pressed = new Date(day);
675
+ pressed.setHours(0, 0, 0, 0);
676
+ pressed.setMinutes(minutes);
677
+ return pressed;
678
+ };
679
+ const handleBackgroundPress = (event) => {
680
+ const date = onPressCell && cellDateFromTouch(event);
681
+ if (date) onPressCell?.(date);
682
+ };
683
+ const handleBackgroundLongPress = (event) => {
684
+ const date = onLongPressCell && cellDateFromTouch(event);
685
+ if (date) onLongPressCell?.(date);
686
+ };
687
+ const hoursRange = (0, react.useMemo)(() => Array.from({ length: maxHour - minHour }, (_, index) => minHour + index), [minHour, maxHour]);
688
+ const now = useNow(showNowIndicator && isActive);
689
+ const nowDayIndex = days.findIndex((day) => (0, _super_calendar_core.getIsToday)(day));
690
+ const nowHours = ((0, date_fns.getHours)(now) * MINUTES_PER_HOUR + (0, date_fns.getMinutes)(now)) / MINUTES_PER_HOUR;
691
+ const nowInWindow = nowHours >= minHour && nowHours <= maxHour;
692
+ const fullHeightStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ height: (maxHour - minHour) * heightSource.value }), [
693
+ minHour,
694
+ maxHour,
695
+ heightSource
696
+ ]);
697
+ const pinchStartCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
698
+ const zoomGesture = (0, react.useMemo)(() => {
699
+ const pinch = react_native_gesture_handler.Gesture.Pinch().onStart(() => {
700
+ pinchStartCellHeight.value = cellHeight.value;
701
+ }).onUpdate((event) => {
702
+ cellHeight.value = Math.min(maxHourHeight, Math.max(minHourHeight, pinchStartCellHeight.value * event.scale));
703
+ }).onEnd(() => {
704
+ committedCellHeight.value = cellHeight.value;
705
+ });
706
+ return react_native_gesture_handler.Gesture.Simultaneous(pinch, react_native_gesture_handler.Gesture.Native());
707
+ }, [
708
+ cellHeight,
709
+ committedCellHeight,
710
+ pinchStartCellHeight,
711
+ minHourHeight,
712
+ maxHourHeight
713
+ ]);
714
+ const createEnabled = onCreateEvent != null;
715
+ const createActive = (0, react_native_reanimated.useSharedValue)(0);
716
+ const createTop = (0, react_native_reanimated.useSharedValue)(0);
717
+ const createHeight = (0, react_native_reanimated.useSharedValue)(0);
718
+ const createLeft = (0, react_native_reanimated.useSharedValue)(0);
719
+ const createWidth = (0, react_native_reanimated.useSharedValue)(0);
720
+ const createStartY = (0, react_native_reanimated.useSharedValue)(0);
721
+ const createDayIndex = (0, react_native_reanimated.useSharedValue)(0);
722
+ const createCancelled = (0, react_native_reanimated.useSharedValue)(0);
723
+ const commitCreate = (0, react.useCallback)((startY, endY, dayIndex) => {
724
+ const day = days[dayIndex];
725
+ if (!day) return;
726
+ const range = (0, _super_calendar_core.cellRangeFromDrag)(day, startY, endY, heightSource.value, minHour, snapMinutes);
727
+ if (range) onCreateEvent?.(range.start, range.end);
728
+ }, [
729
+ days,
730
+ heightSource,
731
+ minHour,
732
+ snapMinutes,
733
+ onCreateEvent
734
+ ]);
735
+ const tapCell = (0, react.useCallback)((x, y) => {
736
+ const day = days[days.length === 1 ? 0 : Math.floor(x / dayWidth)];
737
+ if (!day) return;
738
+ const minutes = Math.round((minHour + y / heightSource.value) * MINUTES_PER_HOUR);
739
+ const pressed = new Date(day);
740
+ pressed.setHours(0, 0, 0, 0);
741
+ pressed.setMinutes(minutes);
742
+ onPressCell?.(pressed);
743
+ }, [
744
+ days,
745
+ dayWidth,
746
+ minHour,
747
+ heightSource,
748
+ onPressCell
749
+ ]);
750
+ const createGesture = (0, react.useMemo)(() => {
751
+ const pan = react_native_gesture_handler.Gesture.Pan().enabled(createEnabled).onStart((event) => {
752
+ const idx = days.length === 1 ? 0 : Math.floor(event.x / dayWidth);
753
+ createDayIndex.value = idx;
754
+ createStartY.value = event.y;
755
+ createLeft.value = hourColumnWidth + idx * dayWidth;
756
+ createWidth.value = dayWidth;
757
+ createTop.value = event.y;
758
+ createHeight.value = 0;
759
+ createActive.value = 1;
760
+ createCancelled.value = 0;
761
+ }).onUpdate((event) => {
762
+ if (createCancelled.value) return;
763
+ const stepPx = snapMinutes / MINUTES_PER_HOUR * heightSource.value;
764
+ const snap = (y) => stepPx > 0 ? Math.round(y / stepPx) * stepPx : y;
765
+ const startSnap = snap(createStartY.value);
766
+ const endSnap = snap(createStartY.value + event.translationY);
767
+ createTop.value = Math.min(startSnap, endSnap);
768
+ createHeight.value = Math.max(Math.abs(endSnap - startSnap), stepPx);
769
+ }).onEnd((event) => {
770
+ createActive.value = 0;
771
+ createHeight.value = 0;
772
+ if (createCancelled.value) return;
773
+ (0, react_native_reanimated.runOnJS)(commitCreate)(createStartY.value, createStartY.value + event.translationY, createDayIndex.value);
774
+ });
775
+ return isWeb ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(DRAG_ACTIVATE_MS);
776
+ }, [
777
+ createEnabled,
778
+ days.length,
779
+ dayWidth,
780
+ hourColumnWidth,
781
+ heightSource,
782
+ snapMinutes,
783
+ commitCreate,
784
+ createActive,
785
+ createTop,
786
+ createHeight,
787
+ createLeft,
788
+ createWidth,
789
+ createStartY,
790
+ createDayIndex,
791
+ createCancelled
792
+ ]);
793
+ const backgroundGesture = (0, react.useMemo)(() => {
794
+ const tap = isWeb && onPressCell != null ? react_native_gesture_handler.Gesture.Tap().onEnd((event) => {
795
+ (0, react_native_reanimated.runOnJS)(tapCell)(event.x, event.y);
796
+ }) : null;
797
+ if (createEnabled && tap) return react_native_gesture_handler.Gesture.Exclusive(createGesture, tap);
798
+ if (createEnabled) return createGesture;
799
+ return tap;
800
+ }, [
801
+ createEnabled,
802
+ createGesture,
803
+ onPressCell,
804
+ tapCell
805
+ ]);
806
+ (0, react.useEffect)(() => {
807
+ if (!isWeb || !createEnabled) return;
808
+ const doc = globalThis.document;
809
+ if (!doc) return;
810
+ const handler = (event) => {
811
+ if (event.key !== "Escape" || !createActive.value) return;
812
+ createCancelled.value = 1;
813
+ createActive.value = 0;
814
+ createHeight.value = 0;
815
+ };
816
+ doc.addEventListener("keydown", handler);
817
+ return () => doc.removeEventListener("keydown", handler);
818
+ }, [
819
+ createEnabled,
820
+ createActive,
821
+ createCancelled,
822
+ createHeight
823
+ ]);
824
+ const createGhostStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
825
+ top: createTop.value,
826
+ height: createHeight.value,
827
+ left: createLeft.value,
828
+ width: createWidth.value,
829
+ opacity: createActive.value
830
+ }));
831
+ const cellLayer = onPressCell || onLongPressCell || createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
832
+ style: [styles.cellPressLayer, { left: hourColumnWidth }],
833
+ onPress: onPressCell ? handleBackgroundPress : void 0,
834
+ onLongPress: !createEnabled && onLongPressCell ? handleBackgroundLongPress : void 0,
835
+ tabIndex: -1,
836
+ importantForAccessibility: "no",
837
+ accessibilityElementsHidden: true
838
+ }) : null;
839
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
840
+ style: styles.container,
841
+ children: [showAllDayEventCell ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AllDayLane, {
842
+ days,
843
+ events,
844
+ mode,
845
+ hourColumnWidth,
846
+ dayWidth,
847
+ renderEvent,
848
+ keyExtractor,
849
+ onPressEvent,
850
+ onLongPressEvent
851
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
852
+ gesture: zoomGesture,
853
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.ScrollView, {
854
+ ref: scrollRef,
855
+ showsVerticalScrollIndicator: showVerticalScrollIndicator,
856
+ scrollEnabled: verticalScrollEnabled,
857
+ onScroll: scrollHandler,
858
+ scrollEventThrottle: 16,
859
+ contentContainerStyle: { paddingTop: HOUR_LABEL_TOP_INSET },
860
+ contentOffset: {
861
+ x: 0,
862
+ y: initialScrollY
863
+ },
864
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
865
+ style: [styles.content, fullHeightStyle],
866
+ children: [
867
+ cellLayer && backgroundGesture ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
868
+ gesture: backgroundGesture,
869
+ children: cellLayer
870
+ }) : cellLayer,
871
+ days.map((day, dayIndex) => (0, _super_calendar_core.isWeekend)(day) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
872
+ styles.weekendColumn,
873
+ styles.nonInteractive,
874
+ { backgroundColor: theme.colors.weekendBackground },
875
+ {
876
+ left: dayLeft(dayIndex),
877
+ width: dayWidth
878
+ },
879
+ fullHeightStyle
880
+ ] }, `weekend-${day.toISOString()}`) : null),
881
+ calendarCellStyle ? days.map((day, dayIndex) => {
882
+ const cellStyle = calendarCellStyle(day);
883
+ return cellStyle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
884
+ styles.weekendColumn,
885
+ styles.nonInteractive,
886
+ {
887
+ left: dayLeft(dayIndex),
888
+ width: dayWidth
889
+ },
890
+ cellStyle,
891
+ fullHeightStyle
892
+ ] }, `cell-${day.toISOString()}`) : null;
893
+ }) : null,
894
+ businessHours ? days.flatMap((day, dayIndex) => (0, _super_calendar_core.closedHourBands)(day, businessHours, minHour, maxHour).map((band, bandIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShadeBand, {
895
+ cellHeight: heightSource,
896
+ startHour: band.start,
897
+ endHour: band.end,
898
+ minHour,
899
+ left: dayLeft(dayIndex),
900
+ width: dayWidth,
901
+ color: theme.colors.outsideHoursBackground
902
+ }, `closed-${day.toISOString()}-${bandIndex}`))) : null,
903
+ days.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
904
+ styles.daySeparator,
905
+ styles.nonInteractive,
906
+ { backgroundColor: theme.colors.gridLine },
907
+ { left: dayLeft(dayIndex) },
908
+ fullHeightStyle
909
+ ] }, `separator-${day.toISOString()}`)),
910
+ hoursRange.map((hour) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HourRow, {
911
+ hour,
912
+ minHour,
913
+ cellHeight: heightSource,
914
+ hourColumnWidth,
915
+ label: (0, _super_calendar_core.formatHour)(hour, { ampm }),
916
+ ampm,
917
+ hourComponent
918
+ }, hour)),
919
+ timeslots > 1 ? hoursRange.flatMap((hour) => Array.from({ length: timeslots - 1 }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeslotLine, {
920
+ hour,
921
+ minHour,
922
+ fraction: (i + 1) / timeslots,
923
+ cellHeight: heightSource,
924
+ hourColumnWidth
925
+ }, `slot-${hour}-${i}`))) : null,
926
+ dayLayouts.flatMap((layout, dayIndex) => layout.filter((p) => p.startHours < maxHour && p.startHours + p.durationHours > minHour).map((positioned, eventIndex) => {
927
+ const columnWidth = dayWidth / positioned.columns;
928
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AnimatedEventBox, {
929
+ positioned,
930
+ cellHeight: heightSource,
931
+ minHour,
932
+ left: dayLeft(dayIndex) + positioned.column * columnWidth,
933
+ width: columnWidth,
934
+ dayWidth,
935
+ dayIndex,
936
+ dayCount: days.length,
937
+ mode,
938
+ renderEvent,
939
+ snapMinutes,
940
+ showDragHandle,
941
+ onPress: onPressEvent,
942
+ onLongPress: onLongPressEvent,
943
+ onDragEvent,
944
+ onDragStart
945
+ }, `${dayIndex}:${keyExtractor(positioned.event, eventIndex)}`);
946
+ })),
947
+ showNowIndicator && nowDayIndex >= 0 && nowInWindow ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NowIndicator, {
948
+ cellHeight: heightSource,
949
+ nowHours,
950
+ minHour,
951
+ left: dayLeft(nowDayIndex),
952
+ width: dayWidth,
953
+ color: theme.colors.nowIndicator
954
+ }) : null,
955
+ createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
956
+ styles.createGhost,
957
+ { pointerEvents: "none" },
958
+ {
959
+ backgroundColor: theme.colors.eventBackground,
960
+ borderColor: theme.colors.todayBackground
961
+ },
962
+ createGhostStyle
963
+ ] }) : null
964
+ ]
965
+ })
966
+ })
967
+ })]
968
+ });
969
+ }
970
+ const TimetablePage = (0, react.memo)(TimetablePageInner);
971
+ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellHeight, hourHeight = 48, weekStartsOn, renderEvent, keyExtractor, scrollOffsetMinutes = 0, hourColumnWidth: hourColumnWidthProp = DEFAULT_HOUR_COLUMN_WIDTH, hideHours = false, timeslots = 1, showAllDayEventCell = true, calendarCellStyle, businessHours, showWeekNumber = false, headerComponent, minHour = 0, maxHour = HOURS_PER_DAY, ampm = false, isRTL = false, minHourHeight = DEFAULT_MIN_HOUR_HEIGHT, maxHourHeight = DEFAULT_MAX_HOUR_HEIGHT, showNowIndicator = true, locale, freeSwipe = false, swipeEnabled = true, showVerticalScrollIndicator = true, verticalScrollEnabled = true, weekNumberPrefix = "W", hourComponent, activeDate, resetPageOnPressCell = false, dragStepMinutes = DEFAULT_DRAG_STEP_MINUTES, showDragHandle = true, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, onPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, onChangeDate, renderHeader }) {
972
+ const clampedMinHour = Math.max(0, Math.min(minHour, HOURS_PER_DAY - 1));
973
+ const clampedMaxHour = Math.max(clampedMinHour + 1, Math.min(maxHour, HOURS_PER_DAY));
974
+ const hourColumnWidth = hideHours ? 0 : hourColumnWidthProp;
975
+ const { width, height } = (0, react_native.useWindowDimensions)();
976
+ const listRef = (0, react.useRef)(null);
977
+ const containerRef = (0, react.useRef)(null);
978
+ const suppressCaptureUntilRef = (0, react.useRef)(0);
979
+ const [pageHeight, setPageHeight] = (0, react.useState)(height);
980
+ const [containerWidth, setContainerWidth] = (0, react.useState)(width);
981
+ const [measured, setMeasured] = (0, react.useState)(false);
982
+ const weekAnchored = mode === "week" || mode === "custom" && weekEndsOn != null;
983
+ const step = weekAnchored ? 7 : (0, _super_calendar_core.viewDayCount)(mode, numberOfDays);
984
+ const seedDefaultY = Math.max(0, scrollOffsetMinutes / MINUTES_PER_HOUR - clampedMinHour) * hourHeight;
985
+ const scrollY = (0, react_native_reanimated.useSharedValue)(seedDefaultY);
986
+ const offsetSeedRef = (0, react.useRef)(null);
987
+ const captureOffsetSeed = (0, react.useCallback)((y) => {
988
+ offsetSeedRef.current = y;
989
+ }, []);
990
+ const committedCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
991
+ useWebGridZoom(isWeb, containerRef, cellHeight, committedCellHeight, minHourHeight, maxHourHeight);
992
+ const [anchorDate] = (0, react.useState)(date);
993
+ const anchor = (0, react.useMemo)(() => weekAnchored ? (0, date_fns.startOfWeek)(anchorDate, { weekStartsOn }) : (0, date_fns.startOfDay)(anchorDate), [
994
+ weekAnchored,
995
+ anchorDate,
996
+ weekStartsOn
997
+ ]);
998
+ const pageDates = (0, react.useMemo)(() => Array.from({ length: 361 }, (_, i) => (0, date_fns.addDays)(anchor, (i - PAGE_WINDOW) * step)), [anchor, step]);
999
+ const activeIndex = (0, react.useCallback)((target) => {
1000
+ const aligned = weekAnchored ? (0, date_fns.startOfWeek)(target, { weekStartsOn }) : (0, date_fns.startOfDay)(target);
1001
+ return Math.floor((0, date_fns.differenceInCalendarDays)(aligned, anchor) / step) + PAGE_WINDOW;
1002
+ }, [
1003
+ anchor,
1004
+ weekAnchored,
1005
+ step,
1006
+ weekStartsOn
1007
+ ])(date);
1008
+ const viewedIndexRef = (0, react.useRef)(activeIndex);
1009
+ const pendingScrollIndexRef = (0, react.useRef)(null);
1010
+ const headerDays = (0, react.useMemo)(() => (0, _super_calendar_core.getViewDays)(mode, pageDates[activeIndex] ?? date, weekStartsOn, numberOfDays, isRTL, weekEndsOn), [
1011
+ mode,
1012
+ pageDates,
1013
+ activeIndex,
1014
+ date,
1015
+ weekStartsOn,
1016
+ numberOfDays,
1017
+ isRTL,
1018
+ weekEndsOn
1019
+ ]);
1020
+ const handleViewableItemsChanged = (0, react.useCallback)((info) => {
1021
+ if (isWeb) return;
1022
+ const settled = info.viewableItems.find((token) => token.isViewable);
1023
+ if (settled?.index == null) return;
1024
+ if (pendingScrollIndexRef.current != null) {
1025
+ if (settled.index === pendingScrollIndexRef.current) {
1026
+ pendingScrollIndexRef.current = null;
1027
+ viewedIndexRef.current = settled.index;
1028
+ }
1029
+ return;
1030
+ }
1031
+ if (settled.index === viewedIndexRef.current) return;
1032
+ viewedIndexRef.current = settled.index;
1033
+ if (settled.item) onChangeDate(settled.item);
1034
+ }, [onChangeDate]);
1035
+ (0, react.useEffect)(() => {
1036
+ if (activeIndex === viewedIndexRef.current) return;
1037
+ viewedIndexRef.current = activeIndex;
1038
+ pendingScrollIndexRef.current = activeIndex;
1039
+ listRef.current?.scrollToIndex({
1040
+ index: activeIndex,
1041
+ animated: false
1042
+ });
1043
+ }, [activeIndex]);
1044
+ (0, react.useEffect)(() => {
1045
+ if (!isWeb) return;
1046
+ const root = containerRef.current;
1047
+ if (!root) return;
1048
+ const restoreVisiblePage = () => {
1049
+ const vw = (root.ownerDocument?.defaultView ?? globalThis).innerWidth;
1050
+ for (const el of root.querySelectorAll("*")) {
1051
+ const style = getComputedStyle(el);
1052
+ if (!((style.overflowY === "scroll" || style.overflowY === "auto") && el.scrollHeight > el.clientHeight + 20 && el.clientHeight > 100)) continue;
1053
+ const rect = el.getBoundingClientRect();
1054
+ if (rect.left > -50 && rect.right <= vw + 50) {
1055
+ el.scrollTop = scrollY.value;
1056
+ break;
1057
+ }
1058
+ }
1059
+ };
1060
+ suppressCaptureUntilRef.current = Date.now() + 400;
1061
+ let raf2 = 0;
1062
+ const raf1 = requestAnimationFrame(() => {
1063
+ restoreVisiblePage();
1064
+ raf2 = requestAnimationFrame(restoreVisiblePage);
1065
+ });
1066
+ return () => {
1067
+ cancelAnimationFrame(raf1);
1068
+ cancelAnimationFrame(raf2);
1069
+ };
1070
+ }, [activeIndex, pageHeight]);
1071
+ (0, react.useEffect)(() => {
1072
+ if (!isWeb) return;
1073
+ const root = containerRef.current;
1074
+ if (!root) return;
1075
+ const onScrollCapture = (event) => {
1076
+ if (Date.now() < suppressCaptureUntilRef.current) return;
1077
+ const el = event.target;
1078
+ if (!el || typeof el.scrollTop !== "number" || el.clientHeight <= 100) return;
1079
+ const rect = el.getBoundingClientRect();
1080
+ const vw = (root.ownerDocument?.defaultView ?? globalThis).innerWidth;
1081
+ if (rect.left <= -50 || rect.right > vw + 50) return;
1082
+ scrollY.value = el.scrollTop;
1083
+ offsetSeedRef.current = el.scrollTop;
1084
+ };
1085
+ root.addEventListener("scroll", onScrollCapture, true);
1086
+ return () => root.removeEventListener("scroll", onScrollCapture, true);
1087
+ }, []);
1088
+ (0, react.useEffect)(() => {
1089
+ if (!isWeb) return;
1090
+ const root = containerRef.current;
1091
+ if (!root) return;
1092
+ const lockHorizontal = () => {
1093
+ for (const el of root.querySelectorAll("*")) {
1094
+ if (el.scrollWidth <= el.clientWidth + 20 || el.clientWidth <= 100) continue;
1095
+ const overflowX = getComputedStyle(el).overflowX;
1096
+ if (overflowX === "auto" || overflowX === "scroll") {
1097
+ el.style.overflowX = "hidden";
1098
+ el.style.touchAction = "pan-y";
1099
+ }
1100
+ }
1101
+ };
1102
+ const raf = requestAnimationFrame(lockHorizontal);
1103
+ return () => cancelAnimationFrame(raf);
1104
+ }, [pageHeight]);
1105
+ require_MonthList.useWebPagerKeys(swipeEnabled, (0, react.useCallback)((delta) => {
1106
+ const target = pageDates[activeIndex + delta];
1107
+ if (target) onChangeDate(target);
1108
+ }, [
1109
+ pageDates,
1110
+ activeIndex,
1111
+ onChangeDate
1112
+ ]));
1113
+ const handlePressCell = (0, react.useMemo)(() => {
1114
+ if (!onPressCell) return void 0;
1115
+ if (!resetPageOnPressCell) return onPressCell;
1116
+ return (cellDate) => {
1117
+ onPressCell(cellDate);
1118
+ listRef.current?.scrollToIndex({
1119
+ index: activeIndex,
1120
+ animated: true
1121
+ });
1122
+ };
1123
+ }, [
1124
+ onPressCell,
1125
+ resetPageOnPressCell,
1126
+ activeIndex
1127
+ ]);
1128
+ const snapToIndices = (0, react.useMemo)(() => pageDates.map((_, index) => index), [pageDates]);
1129
+ const keyExtractorList = (0, react.useCallback)((item) => item.toISOString(), []);
1130
+ const getFixedItemSize = (0, react.useCallback)(() => containerWidth, [containerWidth]);
1131
+ const renderItem = (0, react.useCallback)(({ item, index }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1132
+ style: {
1133
+ width: containerWidth,
1134
+ height: pageHeight
1135
+ },
1136
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimetablePage, {
1137
+ mode,
1138
+ numberOfDays,
1139
+ date: item,
1140
+ width: containerWidth,
1141
+ events,
1142
+ cellHeight,
1143
+ hourHeight,
1144
+ committedCellHeight,
1145
+ scrollY,
1146
+ isActive: index === activeIndex,
1147
+ initialScrollY: offsetSeedRef.current ?? seedDefaultY,
1148
+ onSettleOffset: captureOffsetSeed,
1149
+ weekStartsOn,
1150
+ weekEndsOn,
1151
+ hourColumnWidth,
1152
+ minHour: clampedMinHour,
1153
+ maxHour: clampedMaxHour,
1154
+ ampm,
1155
+ timeslots,
1156
+ isRTL,
1157
+ showAllDayEventCell,
1158
+ showVerticalScrollIndicator,
1159
+ verticalScrollEnabled,
1160
+ hourComponent,
1161
+ calendarCellStyle,
1162
+ businessHours,
1163
+ minHourHeight,
1164
+ maxHourHeight,
1165
+ showNowIndicator,
1166
+ renderEvent,
1167
+ keyExtractor,
1168
+ snapMinutes: Math.max(1, dragStepMinutes),
1169
+ showDragHandle,
1170
+ onPressEvent,
1171
+ onLongPressEvent,
1172
+ onDragEvent,
1173
+ onDragStart,
1174
+ onPressCell: handlePressCell,
1175
+ onLongPressCell,
1176
+ onCreateEvent
1177
+ })
1178
+ }), [
1179
+ containerWidth,
1180
+ pageHeight,
1181
+ mode,
1182
+ numberOfDays,
1183
+ events,
1184
+ cellHeight,
1185
+ hourHeight,
1186
+ committedCellHeight,
1187
+ scrollY,
1188
+ activeIndex,
1189
+ seedDefaultY,
1190
+ captureOffsetSeed,
1191
+ weekStartsOn,
1192
+ weekEndsOn,
1193
+ hourColumnWidth,
1194
+ clampedMinHour,
1195
+ clampedMaxHour,
1196
+ ampm,
1197
+ timeslots,
1198
+ isRTL,
1199
+ showAllDayEventCell,
1200
+ showVerticalScrollIndicator,
1201
+ verticalScrollEnabled,
1202
+ hourComponent,
1203
+ calendarCellStyle,
1204
+ businessHours,
1205
+ minHourHeight,
1206
+ maxHourHeight,
1207
+ showNowIndicator,
1208
+ renderEvent,
1209
+ keyExtractor,
1210
+ dragStepMinutes,
1211
+ showDragHandle,
1212
+ onPressEvent,
1213
+ onLongPressEvent,
1214
+ onDragEvent,
1215
+ onDragStart,
1216
+ handlePressCell,
1217
+ onLongPressCell,
1218
+ onCreateEvent
1219
+ ]);
1220
+ const listExtraData = (0, react.useMemo)(() => ({
1221
+ events,
1222
+ activeIndex
1223
+ }), [events, activeIndex]);
1224
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1225
+ ref: containerRef,
1226
+ style: styles.container,
1227
+ children: [
1228
+ renderHeader ? renderHeader(headerDays) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultHeader, {
1229
+ days: headerDays,
1230
+ mode,
1231
+ width: containerWidth,
1232
+ hourColumnWidth,
1233
+ showWeekNumber,
1234
+ weekNumberPrefix,
1235
+ locale,
1236
+ activeDate,
1237
+ onPressDateHeader
1238
+ }),
1239
+ headerComponent,
1240
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1241
+ style: styles.pager,
1242
+ onLayout: (event) => {
1243
+ setPageHeight(event.nativeEvent.layout.height);
1244
+ setContainerWidth(event.nativeEvent.layout.width);
1245
+ setMeasured(true);
1246
+ },
1247
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
1248
+ ref: listRef,
1249
+ style: isWeb ? [styles.pagerList, styles.webNoScroll] : styles.pagerList,
1250
+ data: pageDates,
1251
+ extraData: listExtraData,
1252
+ horizontal: true,
1253
+ recycleItems: false,
1254
+ keyExtractor: keyExtractorList,
1255
+ getFixedItemSize,
1256
+ ...isWeb ? null : {
1257
+ scrollEnabled: swipeEnabled,
1258
+ pagingEnabled: !freeSwipe,
1259
+ snapToIndices: freeSwipe ? snapToIndices : void 0
1260
+ },
1261
+ initialScrollIndex: activeIndex,
1262
+ showsHorizontalScrollIndicator: false,
1263
+ viewabilityConfig: PAGE_VIEWABILITY,
1264
+ onViewableItemsChanged: handleViewableItemsChanged,
1265
+ renderItem
1266
+ }, measured ? "grid" : "grid-seed")
1267
+ })
1268
+ ]
1269
+ });
1270
+ }
1271
+ const TimeGrid = (0, react.memo)(TimeGridInner);
1272
+ const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, weekNumberPrefix = "W", locale, activeDate, onPressDateHeader }) => {
1273
+ const theme = require_MonthList.useCalendarTheme();
1274
+ const dayWidth = (width - hourColumnWidth) / days.length;
1275
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1276
+ style: [styles.headerRow, { borderBottomColor: theme.colors.gridLine }],
1277
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1278
+ style: [styles.weekNumberGutter, { width: hourColumnWidth }],
1279
+ children: showWeekNumber && hourColumnWidth > 0 && days[0] ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1280
+ style: [theme.text.hourLabel, { color: theme.colors.textMuted }],
1281
+ allowFontScaling: false,
1282
+ children: `${weekNumberPrefix}${(0, date_fns.getISOWeek)(days[0])}`
1283
+ }) : null
1284
+ }), days.map((day) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DayHeader, {
1285
+ day,
1286
+ mode,
1287
+ width: dayWidth,
1288
+ locale,
1289
+ activeDate,
1290
+ onPressDateHeader
1291
+ }, day.toISOString()))]
1292
+ });
1293
+ };
1294
+ const DayHeader = ({ day, width, locale, activeDate, onPressDateHeader }) => {
1295
+ const theme = require_MonthList.useCalendarTheme();
1296
+ const isToday = (0, _super_calendar_core.getIsToday)(day);
1297
+ const isHighlighted = activeDate ? (0, _super_calendar_core.isSameCalendarDay)(day, activeDate) : isToday;
1298
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Pressable, {
1299
+ style: [styles.dayHeader, { width }],
1300
+ onPress: onPressDateHeader ? () => onPressDateHeader(day) : void 0,
1301
+ disabled: !onPressDateHeader,
1302
+ accessibilityRole: onPressDateHeader ? "button" : void 0,
1303
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1304
+ style: [styles.dayHeaderWeekday, { color: theme.colors.textMuted }],
1305
+ allowFontScaling: false,
1306
+ children: (0, date_fns.format)(day, "EEE", { locale })
1307
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1308
+ style: [styles.dayHeaderBadge, isHighlighted && { backgroundColor: theme.colors.todayBackground }],
1309
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1310
+ style: [styles.dayHeaderNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }],
1311
+ allowFontScaling: false,
1312
+ ...isToday && { accessibilityLabel: `Today, ${day.getDate()}` },
1313
+ children: day.getDate()
1314
+ })
1315
+ })]
1316
+ });
1317
+ };
1318
+ const styles = react_native.StyleSheet.create({
1319
+ pager: { flex: 1 },
1320
+ pagerList: { flex: 1 },
1321
+ container: { flex: 1 },
1322
+ headerRow: {
1323
+ flexDirection: "row",
1324
+ alignItems: "center",
1325
+ borderBottomWidth: react_native.StyleSheet.hairlineWidth
1326
+ },
1327
+ weekNumberGutter: {
1328
+ alignItems: "center",
1329
+ justifyContent: "flex-end"
1330
+ },
1331
+ dayHeader: {
1332
+ alignItems: "center",
1333
+ gap: 2,
1334
+ paddingVertical: 6
1335
+ },
1336
+ dayHeaderWeekday: {
1337
+ fontSize: 11,
1338
+ fontWeight: "600"
1339
+ },
1340
+ dayHeaderBadge: {
1341
+ width: 28,
1342
+ height: 28,
1343
+ borderRadius: 999,
1344
+ justifyContent: "center",
1345
+ alignItems: "center"
1346
+ },
1347
+ dayHeaderNumber: {
1348
+ fontSize: 15,
1349
+ fontWeight: "600"
1350
+ },
1351
+ content: {
1352
+ width: "100%",
1353
+ position: "relative"
1354
+ },
1355
+ cellPressLayer: {
1356
+ position: "absolute",
1357
+ top: 0,
1358
+ bottom: 0,
1359
+ right: 0
1360
+ },
1361
+ createGhost: {
1362
+ position: "absolute",
1363
+ borderRadius: 6,
1364
+ borderWidth: react_native.StyleSheet.hairlineWidth,
1365
+ marginHorizontal: EVENT_GAP
1366
+ },
1367
+ weekendColumn: {
1368
+ position: "absolute",
1369
+ top: 0
1370
+ },
1371
+ shadeBand: { position: "absolute" },
1372
+ daySeparator: {
1373
+ position: "absolute",
1374
+ top: 0,
1375
+ width: react_native.StyleSheet.hairlineWidth
1376
+ },
1377
+ hourRow: {
1378
+ position: "absolute",
1379
+ left: 0,
1380
+ right: 0,
1381
+ flexDirection: "row",
1382
+ alignItems: "flex-start"
1383
+ },
1384
+ hourLabel: {
1385
+ marginTop: -6,
1386
+ textAlign: "right",
1387
+ paddingRight: 6
1388
+ },
1389
+ hourLine: {
1390
+ flex: 1,
1391
+ height: react_native.StyleSheet.hairlineWidth
1392
+ },
1393
+ timeslotLine: {
1394
+ position: "absolute",
1395
+ right: 0,
1396
+ height: react_native.StyleSheet.hairlineWidth,
1397
+ opacity: .5
1398
+ },
1399
+ resizeHandle: {
1400
+ position: "absolute",
1401
+ left: 0,
1402
+ right: 0,
1403
+ bottom: 0,
1404
+ height: RESIZE_HANDLE_HEIGHT,
1405
+ alignItems: "center",
1406
+ justifyContent: "center"
1407
+ },
1408
+ resizeGrip: {
1409
+ width: 24,
1410
+ height: 3,
1411
+ borderRadius: 2,
1412
+ opacity: .4
1413
+ },
1414
+ eventBox: {
1415
+ position: "absolute",
1416
+ overflow: "hidden",
1417
+ padding: EVENT_GAP
1418
+ },
1419
+ nowIndicator: {
1420
+ position: "absolute",
1421
+ height: 2
1422
+ },
1423
+ nonInteractive: { pointerEvents: "none" },
1424
+ webNoScroll: { overflow: "hidden" }
1425
+ });
1426
+ //#endregion
1427
+ //#region src/components/Calendar.tsx
1428
+ const defaultKeyExtractor = (event) => `${event.start.toISOString()}|${event.end.toISOString()}|${event.title ?? ""}`;
1429
+ function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1430
+ if (mode === "month") return [(0, date_fns.startOfWeek)((0, date_fns.startOfMonth)(date), { weekStartsOn }), (0, date_fns.endOfWeek)((0, date_fns.endOfMonth)(date), { weekStartsOn })];
1431
+ const days = (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1432
+ return [(0, date_fns.startOfDay)(days[0]), (0, date_fns.endOfDay)(days[days.length - 1])];
1433
+ }
1434
+ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn = 0, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventCellStyle, calendarCellStyle, businessHours, keyExtractor = defaultKeyExtractor, theme, cellHeight: cellHeightProp, hourHeight = 48, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent }) {
1435
+ const mergedTheme = (0, react.useMemo)(() => require_MonthList.mergeTheme(theme), [theme]);
1436
+ const internalCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
1437
+ const cellHeight = cellHeightProp ?? internalCellHeight;
1438
+ const handlePressEvent = (0, react.useCallback)((event) => {
1439
+ if (!event.disabled) onPressEvent(event);
1440
+ }, [onPressEvent]);
1441
+ const handleLongPressEvent = (0, react.useMemo)(() => onLongPressEvent ? (event) => {
1442
+ if (!event.disabled) onLongPressEvent(event);
1443
+ } : void 0, [onLongPressEvent]);
1444
+ const handleChangeDate = (0, react.useCallback)((next) => {
1445
+ onChangeDate(next);
1446
+ onChangeDateRange?.(visibleRange(mode, next, weekStartsOn, numberOfDays ?? 1, weekEndsOn));
1447
+ }, [
1448
+ onChangeDate,
1449
+ onChangeDateRange,
1450
+ mode,
1451
+ weekStartsOn,
1452
+ numberOfDays,
1453
+ weekEndsOn
1454
+ ]);
1455
+ const resolvedRenderEvent = (0, react.useMemo)(() => {
1456
+ if (eventCellStyle == null && ampm == null && showTime == null && ellipsizeTitle == null && allDayLabel == null) return renderEvent;
1457
+ const Base = renderEvent;
1458
+ return function StyledEvent(props) {
1459
+ const cellStyle = typeof eventCellStyle === "function" ? eventCellStyle(props.event) : eventCellStyle;
1460
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Base, {
1461
+ ...props,
1462
+ cellStyle,
1463
+ ampm,
1464
+ showTime,
1465
+ ellipsizeTitle,
1466
+ allDayLabel
1467
+ });
1468
+ };
1469
+ }, [
1470
+ renderEvent,
1471
+ eventCellStyle,
1472
+ ampm,
1473
+ showTime,
1474
+ ellipsizeTitle,
1475
+ allDayLabel
1476
+ ]);
1477
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MonthList.CalendarThemeProvider, {
1478
+ value: mergedTheme,
1479
+ children: mode === "month" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MonthList.MonthPager, {
1480
+ date,
1481
+ events,
1482
+ maxVisibleEventCount,
1483
+ weekStartsOn,
1484
+ locale,
1485
+ sortedMonthView,
1486
+ moreLabel,
1487
+ showAdjacentMonths,
1488
+ disableMonthEventCellPress,
1489
+ isRTL,
1490
+ showSixWeeks,
1491
+ activeDate,
1492
+ renderHeaderForMonthView,
1493
+ renderCustomDateForMonth,
1494
+ calendarCellStyle,
1495
+ renderEvent: resolvedRenderEvent,
1496
+ keyExtractor,
1497
+ onPressDay,
1498
+ onLongPressDay,
1499
+ onPressEvent: handlePressEvent,
1500
+ onLongPressEvent: handleLongPressEvent,
1501
+ onPressMore,
1502
+ onChangeDate: handleChangeDate,
1503
+ freeSwipe,
1504
+ swipeEnabled
1505
+ }) : mode === "schedule" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Agenda, {
1506
+ events,
1507
+ locale,
1508
+ renderEvent: resolvedRenderEvent,
1509
+ keyExtractor,
1510
+ onPressEvent: handlePressEvent,
1511
+ onLongPressEvent: handleLongPressEvent,
1512
+ onPressDay,
1513
+ activeDate,
1514
+ itemSeparatorComponent
1515
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeGrid, {
1516
+ mode,
1517
+ numberOfDays,
1518
+ weekEndsOn,
1519
+ date,
1520
+ events,
1521
+ cellHeight,
1522
+ hourHeight,
1523
+ weekStartsOn,
1524
+ renderEvent: resolvedRenderEvent,
1525
+ keyExtractor,
1526
+ scrollOffsetMinutes,
1527
+ hourColumnWidth,
1528
+ hideHours,
1529
+ timeslots,
1530
+ showAllDayEventCell,
1531
+ calendarCellStyle,
1532
+ businessHours,
1533
+ showWeekNumber,
1534
+ weekNumberPrefix,
1535
+ hourComponent,
1536
+ showVerticalScrollIndicator,
1537
+ verticalScrollEnabled,
1538
+ headerComponent,
1539
+ minHour,
1540
+ maxHour,
1541
+ ampm,
1542
+ minHourHeight,
1543
+ maxHourHeight,
1544
+ showNowIndicator,
1545
+ locale,
1546
+ activeDate,
1547
+ isRTL,
1548
+ freeSwipe,
1549
+ swipeEnabled,
1550
+ onPressEvent: handlePressEvent,
1551
+ onLongPressEvent: handleLongPressEvent,
1552
+ onDragEvent,
1553
+ showDragHandle,
1554
+ onDragStart,
1555
+ dragStepMinutes,
1556
+ onPressCell,
1557
+ resetPageOnPressCell,
1558
+ onLongPressCell,
1559
+ onCreateEvent,
1560
+ onPressDateHeader,
1561
+ onChangeDate: handleChangeDate,
1562
+ renderHeader: renderTimeGridHeader
1563
+ })
1564
+ });
1565
+ }
1566
+ //#endregion
1567
+ exports.Agenda = Agenda;
1568
+ exports.Calendar = Calendar;
1569
+ exports.CalendarThemeProvider = require_MonthList.CalendarThemeProvider;
1570
+ exports.DEFAULT_HOUR_HEIGHT = DEFAULT_HOUR_HEIGHT;
1571
+ exports.DefaultEvent = DefaultEvent;
1572
+ exports.DefaultMonthEvent = require_MonthList.DefaultMonthEvent;
1573
+ exports.MonthList = require_MonthList.MonthList;
1574
+ exports.MonthPager = require_MonthList.MonthPager;
1575
+ exports.MonthView = require_MonthList.MonthView;
1576
+ exports.TimeGrid = TimeGrid;
1577
+ Object.defineProperty(exports, "buildMonthGrid", {
1578
+ enumerable: true,
1579
+ get: function() {
1580
+ return _super_calendar_core.buildMonthGrid;
1581
+ }
1582
+ });
1583
+ Object.defineProperty(exports, "buildMonthWeeks", {
1584
+ enumerable: true,
1585
+ get: function() {
1586
+ return _super_calendar_core.buildMonthWeeks;
1587
+ }
1588
+ });
1589
+ exports.darkTheme = require_MonthList.darkTheme;
1590
+ Object.defineProperty(exports, "daySelectionState", {
1591
+ enumerable: true,
1592
+ get: function() {
1593
+ return _super_calendar_core.daySelectionState;
1594
+ }
1595
+ });
1596
+ exports.defaultTheme = require_MonthList.defaultTheme;
1597
+ Object.defineProperty(exports, "eventsInTimeZone", {
1598
+ enumerable: true,
1599
+ get: function() {
1600
+ return _super_calendar_core.eventsInTimeZone;
1601
+ }
1602
+ });
1603
+ Object.defineProperty(exports, "expandRecurringEvents", {
1604
+ enumerable: true,
1605
+ get: function() {
1606
+ return _super_calendar_core.expandRecurringEvents;
1607
+ }
1608
+ });
1609
+ Object.defineProperty(exports, "getIsToday", {
1610
+ enumerable: true,
1611
+ get: function() {
1612
+ return _super_calendar_core.getIsToday;
1613
+ }
1614
+ });
1615
+ Object.defineProperty(exports, "getViewDays", {
1616
+ enumerable: true,
1617
+ get: function() {
1618
+ return _super_calendar_core.getViewDays;
1619
+ }
1620
+ });
1621
+ Object.defineProperty(exports, "getWeekDays", {
1622
+ enumerable: true,
1623
+ get: function() {
1624
+ return _super_calendar_core.getWeekDays;
1625
+ }
1626
+ });
1627
+ Object.defineProperty(exports, "isAllDayEvent", {
1628
+ enumerable: true,
1629
+ get: function() {
1630
+ return _super_calendar_core.isAllDayEvent;
1631
+ }
1632
+ });
1633
+ Object.defineProperty(exports, "isDateSelectable", {
1634
+ enumerable: true,
1635
+ get: function() {
1636
+ return _super_calendar_core.isDateSelectable;
1637
+ }
1638
+ });
1639
+ Object.defineProperty(exports, "isRangeEndpoint", {
1640
+ enumerable: true,
1641
+ get: function() {
1642
+ return _super_calendar_core.isRangeEndpoint;
1643
+ }
1644
+ });
1645
+ Object.defineProperty(exports, "isSameCalendarDay", {
1646
+ enumerable: true,
1647
+ get: function() {
1648
+ return _super_calendar_core.isSameCalendarDay;
1649
+ }
1650
+ });
1651
+ Object.defineProperty(exports, "isWeekend", {
1652
+ enumerable: true,
1653
+ get: function() {
1654
+ return _super_calendar_core.isWeekend;
1655
+ }
1656
+ });
1657
+ Object.defineProperty(exports, "isWithinDateRange", {
1658
+ enumerable: true,
1659
+ get: function() {
1660
+ return _super_calendar_core.isWithinDateRange;
1661
+ }
1662
+ });
1663
+ Object.defineProperty(exports, "layoutDayEvents", {
1664
+ enumerable: true,
1665
+ get: function() {
1666
+ return _super_calendar_core.layoutDayEvents;
1667
+ }
1668
+ });
1669
+ exports.mergeTheme = require_MonthList.mergeTheme;
1670
+ Object.defineProperty(exports, "minutesIntoDay", {
1671
+ enumerable: true,
1672
+ get: function() {
1673
+ return _super_calendar_core.minutesIntoDay;
1674
+ }
1675
+ });
1676
+ Object.defineProperty(exports, "nextDateRange", {
1677
+ enumerable: true,
1678
+ get: function() {
1679
+ return _super_calendar_core.nextDateRange;
1680
+ }
1681
+ });
1682
+ Object.defineProperty(exports, "toZonedTime", {
1683
+ enumerable: true,
1684
+ get: function() {
1685
+ return _super_calendar_core.toZonedTime;
1686
+ }
1687
+ });
1688
+ exports.useCalendarTheme = require_MonthList.useCalendarTheme;
1689
+ Object.defineProperty(exports, "useDateRange", {
1690
+ enumerable: true,
1691
+ get: function() {
1692
+ return _super_calendar_core.useDateRange;
1693
+ }
1694
+ });
1695
+ Object.defineProperty(exports, "useMonthGrid", {
1696
+ enumerable: true,
1697
+ get: function() {
1698
+ return _super_calendar_core.useMonthGrid;
1699
+ }
1700
+ });