@super-calendar/native 2.3.2 → 2.5.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 CHANGED
@@ -21,7 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
- const require_MonthList = require("./MonthList-CFXm7BK_.js");
24
+ const require_MonthList = require("./MonthList-Aczb2RSY.js");
25
25
  let date_fns = require("date-fns");
26
26
  let react = require("react");
27
27
  let react_native_reanimated = require("react-native-reanimated");
@@ -37,8 +37,12 @@ let react_native_gesture_handler = require("react-native-gesture-handler");
37
37
  * start, grouped under a date header per day. The consumer controls which
38
38
  * events (and therefore which date range) are shown.
39
39
  */
40
- function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLongPressEvent, onPressDay, activeDate, itemSeparatorComponent }) {
40
+ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLongPressEvent, onPressDay, activeDate, itemSeparatorComponent, classNames, styles: styleOverrides }) {
41
41
  const theme = require_MonthList.useCalendarTheme();
42
+ const slot = (0, react.useMemo)(() => require_MonthList.createSlots({
43
+ classNames,
44
+ styles: styleOverrides
45
+ }), [classNames, styleOverrides]);
42
46
  const RenderEventComponent = renderEvent;
43
47
  const rows = (0, react.useMemo)(() => {
44
48
  const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
@@ -67,14 +71,20 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
67
71
  if (item.kind === "header") {
68
72
  const isHighlighted = activeDate ? (0, date_fns.isSameDay)(item.date, activeDate) : (0, _super_calendar_core.getIsToday)(item.date);
69
73
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
70
- style: [styles$4.header, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }],
74
+ ...slot("dayHeader", {
75
+ base: styles$4.header,
76
+ themed: [styles$4.headerText, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }]
77
+ }),
71
78
  onPress: onPressDay ? () => onPressDay(item.date) : void 0,
72
79
  accessibilityRole: onPressDay ? "button" : "header",
73
80
  children: (0, date_fns.format)(item.date, "EEEE, d LLLL", { locale })
74
81
  });
75
82
  }
76
83
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
77
- style: [styles$4.eventRow, theme.containers.agendaRow],
84
+ ...slot("eventRow", {
85
+ base: styles$4.eventRow,
86
+ themed: theme.containers.agendaRow
87
+ }),
78
88
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
79
89
  event: item.event,
80
90
  mode: "schedule",
@@ -90,10 +100,14 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
90
100
  onPressDay,
91
101
  onPressEvent,
92
102
  onLongPressEvent,
93
- RenderEventComponent
103
+ RenderEventComponent,
104
+ slot
94
105
  ]);
95
106
  if (rows.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
96
- style: [styles$4.empty, { color: theme.colors.textMuted }],
107
+ ...slot("empty", {
108
+ base: styles$4.empty,
109
+ themed: [styles$4.emptyText, { color: theme.colors.textMuted }]
110
+ }),
97
111
  children: "No events"
98
112
  });
99
113
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
@@ -108,21 +122,23 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
108
122
  const styles$4 = react_native.StyleSheet.create({
109
123
  list: { flex: 1 },
110
124
  header: {
111
- fontSize: 13,
112
- fontWeight: "600",
113
125
  paddingTop: 12,
114
126
  paddingBottom: 4,
115
127
  paddingHorizontal: 12
116
128
  },
129
+ headerText: {
130
+ fontSize: 13,
131
+ fontWeight: "600"
132
+ },
117
133
  eventRow: {
118
134
  paddingHorizontal: 12,
119
135
  paddingVertical: 2
120
136
  },
121
137
  empty: {
122
- fontSize: 14,
123
138
  paddingVertical: 16,
124
139
  paddingHorizontal: 12
125
- }
140
+ },
141
+ emptyText: { fontSize: 14 }
126
142
  });
127
143
  //#endregion
128
144
  //#region src/components/DefaultEvent.tsx
@@ -138,7 +154,7 @@ const numericStyle = (value, fallback) => typeof value === "number" ? value : fa
138
154
  * only shows once a full line is free beneath the title. Pass your own
139
155
  * `renderEvent` to `<Calendar>` to replace it entirely.
140
156
  */
141
- function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, accessibilityLabel: accessibilityLabelProp, cellStyle, onPress, onLongPress }) {
157
+ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, accessibilityLabel: accessibilityLabelProp, accessibilityActions, onAccessibilityAction, cellStyle, onPress, onLongPress }) {
142
158
  const theme = require_MonthList.useCalendarTheme();
143
159
  const isAllDayEvent = isAllDay ?? false;
144
160
  const timeLabel = (0, _super_calendar_core.eventTimeLabel)({
@@ -200,6 +216,8 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
200
216
  accessibilityRole: "button",
201
217
  accessibilityLabel,
202
218
  accessibilityState: { disabled: event.disabled ?? false },
219
+ accessibilityActions,
220
+ onAccessibilityAction,
203
221
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
204
222
  testID: "event-chip-content",
205
223
  style: [styles$3.content, contentStyle],
@@ -322,6 +340,7 @@ function useWebGridZoom(enabled, target, cellHeight, committedCellHeight, minHei
322
340
  */
323
341
  function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent, keyExtractor, onPressEvent, onLongPressEvent }) {
324
342
  const theme = require_MonthList.useCalendarTheme();
343
+ const slot = require_MonthList.useSlots();
325
344
  const RenderEventComponent = renderEvent;
326
345
  const allDay = events.filter(_super_calendar_core.isAllDayEvent);
327
346
  const perDay = days.map((day) => {
@@ -331,26 +350,27 @@ function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent
331
350
  });
332
351
  if (perDay.every((list) => list.length === 0)) return null;
333
352
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
334
- style: [
335
- styles$2.lane,
336
- { borderBottomColor: theme.colors.gridLine },
337
- theme.containers.allDayLane
338
- ],
353
+ ...slot("allDayLane", {
354
+ base: styles$2.lane,
355
+ themed: [{ borderBottomColor: theme.colors.gridLine }, theme.containers.allDayLane]
356
+ }),
339
357
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
340
358
  style: [styles$2.gutter, { width: hourColumnWidth }],
341
359
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
342
- style: [styles$2.label, { color: theme.colors.textMuted }],
360
+ ...slot("allDayLabel", {
361
+ base: styles$2.label,
362
+ themed: { color: theme.colors.textMuted }
363
+ }),
343
364
  allowFontScaling: false,
344
365
  children: "all-day"
345
366
  })
346
367
  }), days.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
347
- style: [
348
- styles$2.column,
349
- { width: dayWidth },
350
- theme.containers.allDayColumn
351
- ],
368
+ ...slot("allDayColumn", {
369
+ base: [styles$2.column, { width: dayWidth }],
370
+ themed: theme.containers.allDayColumn
371
+ }),
352
372
  children: perDay[dayIndex].map((event, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
353
- style: styles$2.chip,
373
+ ...slot("allDayEvent", { base: styles$2.chip }),
354
374
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
355
375
  event,
356
376
  mode,
@@ -382,7 +402,7 @@ const styles$2 = react_native.StyleSheet.create({
382
402
  });
383
403
  //#endregion
384
404
  //#region src/components/TimeGrid.tsx
385
- const isWeb = react_native.Platform.OS === "web";
405
+ const isWeb$1 = react_native.Platform.OS === "web";
386
406
  const MINUTES_PER_HOUR$1 = 60;
387
407
  const HOURS_PER_DAY = 24;
388
408
  const MINUTES_PER_DAY = MINUTES_PER_HOUR$1 * HOURS_PER_DAY;
@@ -397,7 +417,7 @@ const MIN_EVENT_HEIGHT = 32;
397
417
  const EVENT_GAP = 2;
398
418
  const DRAG_ACTIVATE_MS = 300;
399
419
  const MOVE_ACTIVATE_MS$1 = 500;
400
- const DRAG_ACTIVATE_PX = 8;
420
+ const DRAG_ACTIVATE_PX$1 = 8;
401
421
  const RESIZE_HANDLE_HEIGHT = 14;
402
422
  const DEFAULT_DRAG_STEP_MINUTES = 15;
403
423
  const HOUR_LABEL_TOP_INSET = 12;
@@ -415,6 +435,7 @@ function useNow(enabled) {
415
435
  function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWidth, dayIndex, dayCount, mode, renderEvent, snapMinutes, onPress, onLongPress, onDragEvent, onDragStart, showDragHandle }) {
416
436
  const RenderEventComponent = renderEvent;
417
437
  const theme = require_MonthList.useCalendarTheme();
438
+ const slot = require_MonthList.useSlots();
418
439
  const draggable = onDragEvent != null && !positioned.event.disabled;
419
440
  const resizable = draggable && !positioned.continuesAfter;
420
441
  const moveOffset = (0, react_native_reanimated.useSharedValue)(0);
@@ -495,7 +516,7 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
495
516
  const totalDelta = minuteDelta + dayDelta * MINUTES_PER_DAY;
496
517
  (0, react_native_reanimated.runOnJS)(commitDrag)(totalDelta, totalDelta);
497
518
  });
498
- return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS$1);
519
+ return isWeb$1 ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX$1]).activeOffsetY([-8, DRAG_ACTIVATE_PX$1]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS$1);
499
520
  }, [
500
521
  draggable,
501
522
  snapMinutes,
@@ -530,22 +551,58 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
530
551
  ]);
531
552
  const handlePress = () => onPress(positioned.event);
532
553
  const handleLongPress = !draggable && onLongPress ? () => onLongPress(positioned.event) : void 0;
554
+ const unit = (n) => `${n} minute${n === 1 ? "" : "s"}`;
555
+ const accessibilityActions = draggable ? [
556
+ {
557
+ name: "move-later",
558
+ label: `Move ${unit(snapMinutes)} later`
559
+ },
560
+ {
561
+ name: "move-earlier",
562
+ label: `Move ${unit(snapMinutes)} earlier`
563
+ },
564
+ ...resizable ? [{
565
+ name: "extend",
566
+ label: `Extend by ${unit(snapMinutes)}`
567
+ }, {
568
+ name: "shrink",
569
+ label: `Shorten by ${unit(snapMinutes)}`
570
+ }] : []
571
+ ] : void 0;
572
+ const handleAccessibilityAction = draggable ? (e) => {
573
+ switch (e.nativeEvent.actionName) {
574
+ case "move-later":
575
+ commitDrag(snapMinutes, snapMinutes);
576
+ break;
577
+ case "move-earlier":
578
+ commitDrag(-snapMinutes, -snapMinutes);
579
+ break;
580
+ case "extend":
581
+ commitDrag(0, snapMinutes);
582
+ break;
583
+ case "shrink":
584
+ commitDrag(0, -snapMinutes);
585
+ break;
586
+ }
587
+ } : void 0;
588
+ const eventSlot = slot("event", {
589
+ base: [styles$1.eventBox, {
590
+ left,
591
+ width
592
+ }],
593
+ themed: theme.containers.timeGridEvent
594
+ });
533
595
  const box = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
534
- style: [
535
- styles$1.eventBox,
536
- {
537
- left,
538
- width
539
- },
540
- boxStyle,
541
- theme.containers.timeGridEvent
542
- ],
596
+ ...eventSlot,
597
+ style: [eventSlot.style, boxStyle],
543
598
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
544
599
  event: positioned.event,
545
600
  mode,
546
601
  boxHeight,
547
602
  continuesBefore: positioned.continuesBefore,
548
603
  continuesAfter: positioned.continuesAfter,
604
+ accessibilityActions,
605
+ onAccessibilityAction: handleAccessibilityAction,
549
606
  onPress: handlePress,
550
607
  onLongPress: handleLongPress
551
608
  }), resizable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
@@ -564,6 +621,7 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
564
621
  }
565
622
  const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hourComponent }) => {
566
623
  const theme = require_MonthList.useCalendarTheme();
624
+ const slot = require_MonthList.useSlots();
567
625
  const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (hour - minHour) * cellHeight.value }), [hour, minHour]);
568
626
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
569
627
  style: [
@@ -575,52 +633,61 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
575
633
  style: { width: hourColumnWidth },
576
634
  children: hourComponent(hour, ampm)
577
635
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
578
- style: [
579
- theme.text.hourLabel,
580
- styles$1.hourLabel,
581
- {
582
- width: hourColumnWidth,
583
- color: theme.colors.textMuted
584
- }
585
- ],
636
+ ...slot("hourLabel", {
637
+ base: [styles$1.hourLabel, { width: hourColumnWidth }],
638
+ themed: [theme.text.hourLabel, { color: theme.colors.textMuted }]
639
+ }),
586
640
  allowFontScaling: false,
587
641
  children: label
588
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles$1.hourLine, { backgroundColor: theme.colors.gridLine }] })]
642
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { ...slot("gridLines", {
643
+ base: styles$1.hourLine,
644
+ themed: { backgroundColor: theme.colors.gridLine }
645
+ }) })]
589
646
  });
590
647
  };
591
648
  const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth }) => {
592
649
  const theme = require_MonthList.useCalendarTheme();
650
+ const slot = require_MonthList.useSlots();
593
651
  const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (hour - minHour + fraction) * cellHeight.value }), [
594
652
  hour,
595
653
  minHour,
596
654
  fraction
597
655
  ]);
598
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
599
- styles$1.timeslotLine,
600
- styles$1.nonInteractive,
601
- {
602
- left: hourColumnWidth,
603
- backgroundColor: theme.colors.gridLine
604
- },
605
- animatedStyle
606
- ] });
656
+ const lineSlot = slot("gridLines", {
657
+ base: [
658
+ styles$1.timeslotLine,
659
+ styles$1.nonInteractive,
660
+ { left: hourColumnWidth }
661
+ ],
662
+ themed: { backgroundColor: theme.colors.gridLine }
663
+ });
664
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
665
+ ...lineSlot,
666
+ style: [lineSlot.style, animatedStyle]
667
+ });
607
668
  };
608
669
  const NowIndicator = ({ cellHeight, nowHours, minHour, left, width, color }) => {
609
670
  const theme = require_MonthList.useCalendarTheme();
671
+ const slot = require_MonthList.useSlots();
610
672
  const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (nowHours - minHour) * cellHeight.value }), [nowHours, minHour]);
611
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
612
- styles$1.nowIndicator,
613
- styles$1.nonInteractive,
614
- {
615
- left,
616
- width,
617
- backgroundColor: color
618
- },
619
- animatedStyle,
620
- theme.containers.nowIndicator
621
- ] });
673
+ const lineSlot = slot("nowIndicator", {
674
+ base: [
675
+ styles$1.nowIndicator,
676
+ styles$1.nonInteractive,
677
+ {
678
+ left,
679
+ width
680
+ }
681
+ ],
682
+ themed: [{ backgroundColor: color }, theme.containers.nowIndicator]
683
+ });
684
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
685
+ ...lineSlot,
686
+ style: [lineSlot.style, animatedStyle]
687
+ });
622
688
  };
623
689
  const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color }) => {
690
+ const slot = require_MonthList.useSlots();
624
691
  const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
625
692
  top: (startHour - minHour) * cellHeight.value,
626
693
  height: (endHour - startHour) * cellHeight.value
@@ -629,22 +696,26 @@ const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color
629
696
  endHour,
630
697
  minHour
631
698
  ]);
632
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
633
- testID: "business-hours-shade",
634
- style: [
699
+ const bandSlot = slot("businessHours", {
700
+ base: [
635
701
  styles$1.shadeBand,
636
702
  styles$1.nonInteractive,
637
703
  {
638
704
  left,
639
- width,
640
- backgroundColor: color
641
- },
642
- animatedStyle
643
- ]
705
+ width
706
+ }
707
+ ],
708
+ themed: { backgroundColor: color }
709
+ });
710
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
711
+ testID: "business-hours-shade",
712
+ ...bandSlot,
713
+ style: [bandSlot.style, animatedStyle]
644
714
  });
645
715
  };
646
716
  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 }) {
647
717
  const theme = require_MonthList.useCalendarTheme();
718
+ const slot = require_MonthList.useSlots();
648
719
  const scrollRef = (0, react_native_reanimated.useAnimatedRef)();
649
720
  const heightSource = isActive ? cellHeight : committedCellHeight;
650
721
  const isDragging = (0, react_native_reanimated.useSharedValue)(false);
@@ -661,14 +732,14 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
661
732
  },
662
733
  onEndDrag: (event) => {
663
734
  isDragging.value = false;
664
- if (!isWeb && isActiveShared.value) {
735
+ if (!isWeb$1 && isActiveShared.value) {
665
736
  scrollY.value = event.contentOffset.y;
666
737
  (0, react_native_reanimated.runOnJS)(onSettleOffset)(event.contentOffset.y);
667
738
  }
668
739
  },
669
740
  onMomentumEnd: (event) => {
670
741
  isDragging.value = false;
671
- if (!isWeb && isActiveShared.value) {
742
+ if (!isWeb$1 && isActiveShared.value) {
672
743
  scrollY.value = event.contentOffset.y;
673
744
  (0, react_native_reanimated.runOnJS)(onSettleOffset)(event.contentOffset.y);
674
745
  }
@@ -678,7 +749,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
678
749
  if (!isActiveShared.value && current !== previous) (0, react_native_reanimated.scrollTo)(scrollRef, 0, current, false);
679
750
  });
680
751
  (0, react_native_reanimated.useAnimatedReaction)(() => isActiveShared.value, (active, previous) => {
681
- if (isWeb || !active || active === previous) return;
752
+ if (isWeb$1 || !active || active === previous) return;
682
753
  (0, react_native_reanimated.scrollTo)(scrollRef, 0, scrollY.value, false);
683
754
  });
684
755
  const days = (0, react.useMemo)(() => (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, isRTL, weekEndsOn), [
@@ -695,7 +766,8 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
695
766
  const dayLayouts = (0, react.useMemo)(() => days.map((day) => (0, _super_calendar_core.layoutDayEvents)(events, day)), [days, events]);
696
767
  const cellDateFromTouch = (event) => {
697
768
  const { locationX, locationY } = event.nativeEvent;
698
- const day = days[days.length === 1 ? 0 : Math.floor(locationX / dayWidth)];
769
+ const dayIndex = days.length === 1 ? 0 : Math.floor(locationX / dayWidth);
770
+ const day = days[dayIndex];
699
771
  if (!day) return null;
700
772
  const minutes = Math.round((minHour + locationY / heightSource.value) * MINUTES_PER_HOUR$1);
701
773
  const pressed = new Date(day);
@@ -760,7 +832,8 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
760
832
  onCreateEvent
761
833
  ]);
762
834
  const tapCell = (0, react.useCallback)((x, y) => {
763
- const day = days[days.length === 1 ? 0 : Math.floor(x / dayWidth)];
835
+ const dayIndex = days.length === 1 ? 0 : Math.floor(x / dayWidth);
836
+ const day = days[dayIndex];
764
837
  if (!day) return;
765
838
  const minutes = Math.round((minHour + y / heightSource.value) * MINUTES_PER_HOUR$1);
766
839
  const pressed = new Date(day);
@@ -799,7 +872,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
799
872
  if (createCancelled.value) return;
800
873
  (0, react_native_reanimated.runOnJS)(commitCreate)(createStartY.value, createStartY.value + event.translationY, createDayIndex.value);
801
874
  });
802
- return isWeb ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(DRAG_ACTIVATE_MS);
875
+ return isWeb$1 ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX$1]) : pan.activateAfterLongPress(DRAG_ACTIVATE_MS);
803
876
  }, [
804
877
  createEnabled,
805
878
  dayCount,
@@ -818,7 +891,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
818
891
  createCancelled
819
892
  ]);
820
893
  const backgroundGesture = (0, react.useMemo)(() => {
821
- const tap = isWeb && onPressCell != null ? react_native_gesture_handler.Gesture.Tap().onEnd((event) => {
894
+ const tap = isWeb$1 && onPressCell != null ? react_native_gesture_handler.Gesture.Tap().onEnd((event) => {
822
895
  (0, react_native_reanimated.runOnJS)(tapCell)(event.x, event.y);
823
896
  }) : null;
824
897
  if (createEnabled && tap) return react_native_gesture_handler.Gesture.Exclusive(createGesture, tap);
@@ -831,7 +904,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
831
904
  tapCell
832
905
  ]);
833
906
  (0, react.useEffect)(() => {
834
- if (!isWeb || !createEnabled) return;
907
+ if (!isWeb$1 || !createEnabled) return;
835
908
  const doc = globalThis.document;
836
909
  if (!doc) return;
837
910
  const handler = (event) => {
@@ -855,6 +928,13 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
855
928
  width: createWidth.value,
856
929
  opacity: createActive.value
857
930
  }));
931
+ const ghostSlot = slot("createGhost", {
932
+ base: [styles$1.createGhost, { pointerEvents: "none" }],
933
+ themed: {
934
+ backgroundColor: theme.colors.eventBackground,
935
+ borderColor: theme.colors.todayBackground
936
+ }
937
+ });
858
938
  const cellLayer = onPressCell || onLongPressCell || createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
859
939
  style: [styles$1.cellPressLayer, { left: hourColumnWidth }],
860
940
  onPress: onPressCell ? handleBackgroundPress : void 0,
@@ -895,16 +975,24 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
895
975
  gesture: backgroundGesture,
896
976
  children: cellLayer
897
977
  }) : cellLayer,
898
- days.map((day, dayIndex) => (0, _super_calendar_core.isWeekend)(day) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
899
- styles$1.weekendColumn,
900
- styles$1.nonInteractive,
901
- { backgroundColor: theme.colors.weekendBackground },
902
- {
903
- left: dayLeft(dayIndex),
904
- width: dayWidth
905
- },
906
- fullHeightStyle
907
- ] }, `weekend-${day.toISOString()}`) : null),
978
+ days.map((day, dayIndex) => {
979
+ if (!(0, _super_calendar_core.isWeekend)(day)) return null;
980
+ const shadeSlot = slot("weekendShade", {
981
+ base: [
982
+ styles$1.weekendColumn,
983
+ styles$1.nonInteractive,
984
+ {
985
+ left: dayLeft(dayIndex),
986
+ width: dayWidth
987
+ }
988
+ ],
989
+ themed: { backgroundColor: theme.colors.weekendBackground }
990
+ });
991
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
992
+ ...shadeSlot,
993
+ style: [shadeSlot.style, fullHeightStyle]
994
+ }, `weekend-${day.toISOString()}`);
995
+ }),
908
996
  calendarCellStyle ? days.map((day, dayIndex) => {
909
997
  const cellStyle = calendarCellStyle(day);
910
998
  return cellStyle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
@@ -927,13 +1015,20 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
927
1015
  width: dayWidth,
928
1016
  color: theme.colors.outsideHoursBackground
929
1017
  }, `closed-${day.toISOString()}-${bandIndex}`))) : null,
930
- days.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
931
- styles$1.daySeparator,
932
- styles$1.nonInteractive,
933
- { backgroundColor: theme.colors.gridLine },
934
- { left: dayLeft(dayIndex) },
935
- fullHeightStyle
936
- ] }, `separator-${day.toISOString()}`)),
1018
+ days.map((day, dayIndex) => {
1019
+ const separatorSlot = slot("daySeparator", {
1020
+ base: [
1021
+ styles$1.daySeparator,
1022
+ styles$1.nonInteractive,
1023
+ { left: dayLeft(dayIndex) }
1024
+ ],
1025
+ themed: { backgroundColor: theme.colors.gridLine }
1026
+ });
1027
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
1028
+ ...separatorSlot,
1029
+ style: [separatorSlot.style, fullHeightStyle]
1030
+ }, `separator-${day.toISOString()}`);
1031
+ }),
937
1032
  hoursRange.map((hour) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HourRow, {
938
1033
  hour,
939
1034
  minHour,
@@ -979,15 +1074,10 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
979
1074
  width: dayWidth,
980
1075
  color: theme.colors.nowIndicator
981
1076
  }) : null,
982
- createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
983
- styles$1.createGhost,
984
- { pointerEvents: "none" },
985
- {
986
- backgroundColor: theme.colors.eventBackground,
987
- borderColor: theme.colors.todayBackground
988
- },
989
- createGhostStyle
990
- ] }) : null
1077
+ createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
1078
+ ...ghostSlot,
1079
+ style: [ghostSlot.style, createGhostStyle]
1080
+ }) : null
991
1081
  ]
992
1082
  })
993
1083
  })
@@ -995,7 +1085,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
995
1085
  });
996
1086
  }
997
1087
  const TimetablePage = (0, react.memo)(TimetablePageInner);
998
- function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellHeight, hourHeight = 48, weekStartsOn, weekdayFormat = "short", renderEvent, eventAccessibilityLabel, 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 }) {
1088
+ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellHeight, hourHeight = 48, weekStartsOn, weekdayFormat = "short", renderEvent, eventAccessibilityLabel, 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, classNames, styles: styleOverrides }) {
999
1089
  const clampedMinHour = Math.max(0, Math.min(minHour, HOURS_PER_DAY - 1));
1000
1090
  const clampedMaxHour = Math.max(clampedMinHour + 1, Math.min(maxHour, HOURS_PER_DAY));
1001
1091
  const hourColumnWidth = hideHours ? 0 : hourColumnWidthProp;
@@ -1020,7 +1110,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1020
1110
  offsetSeedRef.current = y;
1021
1111
  }, []);
1022
1112
  const committedCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
1023
- useWebGridZoom(isWeb, containerRef, cellHeight, committedCellHeight, minHourHeight, maxHourHeight);
1113
+ useWebGridZoom(isWeb$1, containerRef, cellHeight, committedCellHeight, minHourHeight, maxHourHeight);
1024
1114
  const [anchorDate] = (0, react.useState)(date);
1025
1115
  const anchor = (0, react.useMemo)(() => weekAnchored ? (0, date_fns.startOfWeek)(anchorDate, { weekStartsOn }) : (0, date_fns.startOfDay)(anchorDate), [
1026
1116
  weekAnchored,
@@ -1050,7 +1140,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1050
1140
  weekEndsOn
1051
1141
  ]);
1052
1142
  const handleViewableItemsChanged = (0, react.useCallback)((info) => {
1053
- if (isWeb) return;
1143
+ if (isWeb$1) return;
1054
1144
  const settled = info.viewableItems.find((token) => token.isViewable);
1055
1145
  if (settled?.index == null) return;
1056
1146
  if (pendingScrollIndexRef.current != null) {
@@ -1074,7 +1164,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1074
1164
  });
1075
1165
  }, [activeIndex]);
1076
1166
  (0, react.useEffect)(() => {
1077
- if (!isWeb) return;
1167
+ if (!isWeb$1) return;
1078
1168
  const root = containerRef.current;
1079
1169
  if (!root) return;
1080
1170
  const restoreVisiblePage = () => {
@@ -1101,7 +1191,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1101
1191
  };
1102
1192
  }, [activeIndex, pageHeight]);
1103
1193
  (0, react.useEffect)(() => {
1104
- if (!isWeb) return;
1194
+ if (!isWeb$1) return;
1105
1195
  const root = containerRef.current;
1106
1196
  if (!root) return;
1107
1197
  const onScrollCapture = (event) => {
@@ -1118,7 +1208,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1118
1208
  return () => root.removeEventListener("scroll", onScrollCapture, true);
1119
1209
  }, []);
1120
1210
  (0, react.useEffect)(() => {
1121
- if (!isWeb) return;
1211
+ if (!isWeb$1) return;
1122
1212
  const root = containerRef.current;
1123
1213
  if (!root) return;
1124
1214
  const lockHorizontal = () => {
@@ -1142,6 +1232,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1142
1232
  activeIndex,
1143
1233
  onChangeDate
1144
1234
  ]));
1235
+ const reduceMotion = (0, react_native_reanimated.useReducedMotion)();
1145
1236
  const handlePressCell = (0, react.useMemo)(() => {
1146
1237
  if (!onPressCell) return void 0;
1147
1238
  if (!resetPageOnPressCell) return onPressCell;
@@ -1149,13 +1240,14 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1149
1240
  onPressCell(cellDate);
1150
1241
  listRef.current?.scrollToIndex({
1151
1242
  index: activeIndex,
1152
- animated: true
1243
+ animated: !reduceMotion
1153
1244
  });
1154
1245
  };
1155
1246
  }, [
1156
1247
  onPressCell,
1157
1248
  resetPageOnPressCell,
1158
- activeIndex
1249
+ activeIndex,
1250
+ reduceMotion
1159
1251
  ]);
1160
1252
  const snapToIndices = (0, react.useMemo)(() => pageDates.map((_, index) => index), [pageDates]);
1161
1253
  const keyExtractorList = (0, react.useCallback)((item) => item.toISOString(), []);
@@ -1253,52 +1345,56 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1253
1345
  events,
1254
1346
  activeIndex
1255
1347
  }), [events, activeIndex]);
1256
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1257
- ref: containerRef,
1258
- style: styles$1.container,
1259
- children: [
1260
- renderHeader ? renderHeader(headerDays) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultHeader, {
1261
- days: headerDays,
1262
- mode,
1263
- width: containerWidth,
1264
- hourColumnWidth,
1265
- showWeekNumber,
1266
- weekNumberPrefix,
1267
- weekdayFormat,
1268
- locale,
1269
- activeDate,
1270
- onPressDateHeader
1271
- }),
1272
- headerComponent,
1273
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1274
- style: styles$1.pager,
1275
- onLayout: (event) => {
1276
- setPageHeight(event.nativeEvent.layout.height);
1277
- setContainerWidth(event.nativeEvent.layout.width);
1278
- setMeasured(true);
1279
- },
1280
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
1281
- ref: listRef,
1282
- style: isWeb ? [styles$1.pagerList, styles$1.webNoScroll] : styles$1.pagerList,
1283
- data: pageDates,
1284
- extraData: listExtraData,
1285
- horizontal: true,
1286
- recycleItems: false,
1287
- keyExtractor: keyExtractorList,
1288
- getFixedItemSize,
1289
- ...isWeb ? null : {
1290
- scrollEnabled: swipeEnabled,
1291
- pagingEnabled: !freeSwipe,
1292
- snapToIndices: freeSwipe ? snapToIndices : void 0
1348
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MonthList.SlotStylesProvider, {
1349
+ classNames,
1350
+ styles: styleOverrides,
1351
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1352
+ ref: containerRef,
1353
+ style: styles$1.container,
1354
+ children: [
1355
+ renderHeader ? renderHeader(headerDays) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultHeader, {
1356
+ days: headerDays,
1357
+ mode,
1358
+ width: containerWidth,
1359
+ hourColumnWidth,
1360
+ showWeekNumber,
1361
+ weekNumberPrefix,
1362
+ weekdayFormat,
1363
+ locale,
1364
+ activeDate,
1365
+ onPressDateHeader
1366
+ }),
1367
+ headerComponent,
1368
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1369
+ style: styles$1.pager,
1370
+ onLayout: (event) => {
1371
+ setPageHeight(event.nativeEvent.layout.height);
1372
+ setContainerWidth(event.nativeEvent.layout.width);
1373
+ setMeasured(true);
1293
1374
  },
1294
- initialScrollIndex: activeIndex,
1295
- showsHorizontalScrollIndicator: false,
1296
- viewabilityConfig: PAGE_VIEWABILITY,
1297
- onViewableItemsChanged: handleViewableItemsChanged,
1298
- renderItem
1299
- }, measured ? "grid" : "grid-seed")
1300
- })
1301
- ]
1375
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
1376
+ ref: listRef,
1377
+ style: isWeb$1 ? [styles$1.pagerList, styles$1.webNoScroll] : styles$1.pagerList,
1378
+ data: pageDates,
1379
+ extraData: listExtraData,
1380
+ horizontal: true,
1381
+ recycleItems: false,
1382
+ keyExtractor: keyExtractorList,
1383
+ getFixedItemSize,
1384
+ ...isWeb$1 ? null : {
1385
+ scrollEnabled: swipeEnabled,
1386
+ pagingEnabled: !freeSwipe,
1387
+ snapToIndices: freeSwipe ? snapToIndices : void 0
1388
+ },
1389
+ initialScrollIndex: activeIndex,
1390
+ showsHorizontalScrollIndicator: false,
1391
+ viewabilityConfig: PAGE_VIEWABILITY,
1392
+ onViewableItemsChanged: handleViewableItemsChanged,
1393
+ renderItem
1394
+ }, measured ? "grid" : "grid-seed")
1395
+ })
1396
+ ]
1397
+ })
1302
1398
  });
1303
1399
  }
1304
1400
  /**
@@ -1323,15 +1419,19 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1323
1419
  const TimeGrid = (0, react.memo)(TimeGridInner);
1324
1420
  const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, weekNumberPrefix = "W", weekdayFormat, locale, activeDate, onPressDateHeader }) => {
1325
1421
  const theme = require_MonthList.useCalendarTheme();
1422
+ const slot = require_MonthList.useSlots();
1326
1423
  const dayWidth = (width - hourColumnWidth) / days.length;
1327
1424
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1328
- style: [styles$1.headerRow, { borderBottomColor: theme.colors.gridLine }],
1425
+ ...slot("header", {
1426
+ base: styles$1.headerRow,
1427
+ themed: { borderBottomColor: theme.colors.gridLine }
1428
+ }),
1329
1429
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1330
1430
  style: [styles$1.weekNumberGutter, { width: hourColumnWidth }],
1331
1431
  children: showWeekNumber && hourColumnWidth > 0 && days[0] ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1332
- style: [theme.text.hourLabel, { color: theme.colors.textMuted }],
1432
+ ...slot("weekNumber", { themed: [theme.text.hourLabel, { color: theme.colors.textMuted }] }),
1333
1433
  allowFontScaling: false,
1334
- children: `${weekNumberPrefix}${(0, date_fns.getISOWeek)(days[0])}`
1434
+ children: `${weekNumberPrefix}${(0, date_fns.getISOWeek)(days.find((d) => d.getDay() === 4) ?? days[0])}`
1335
1435
  }) : null
1336
1436
  }), days.map((day) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DayHeader, {
1337
1437
  day,
@@ -1346,36 +1446,42 @@ const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, wee
1346
1446
  };
1347
1447
  const DayHeader = ({ day, width, weekdayFormat = "short", locale, activeDate, onPressDateHeader }) => {
1348
1448
  const theme = require_MonthList.useCalendarTheme();
1449
+ const slot = require_MonthList.useSlots();
1349
1450
  const isToday = (0, _super_calendar_core.getIsToday)(day);
1350
1451
  const isHighlighted = activeDate ? (0, _super_calendar_core.isSameCalendarDay)(day, activeDate) : isToday;
1351
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Pressable, {
1352
- style: [
1353
- styles$1.dayHeader,
1354
- { width },
1355
- theme.containers.columnHeader
1356
- ],
1357
- onPress: onPressDateHeader ? () => onPressDateHeader(day) : void 0,
1358
- disabled: !onPressDateHeader,
1359
- accessibilityRole: onPressDateHeader ? "button" : void 0,
1360
- accessibilityLabel: onPressDateHeader ? (0, date_fns.format)(day, "EEEE d MMMM", { locale }) : void 0,
1361
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1362
- style: [{ color: theme.colors.textMuted }, theme.text.columnHeaderWeekday],
1452
+ const accessibilityLabel = `${(0, date_fns.format)(day, "EEEE d MMMM", { locale })}${isToday ? ", today" : ""}`;
1453
+ const headerSlot = slot("columnHeader", {
1454
+ base: [styles$1.dayHeader, { width }],
1455
+ themed: theme.containers.columnHeader
1456
+ });
1457
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1458
+ ...slot("columnHeaderWeekday", { themed: [{ color: theme.colors.textMuted }, theme.text.columnHeaderWeekday] }),
1459
+ allowFontScaling: false,
1460
+ children: (0, date_fns.format)(day, (0, _super_calendar_core.weekdayFormatToken)(weekdayFormat), { locale })
1461
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1462
+ testID: "column-header-badge",
1463
+ ...slot("columnHeaderDate", {
1464
+ base: styles$1.dayHeaderBadge,
1465
+ themed: [theme.containers.columnHeaderBadge, isHighlighted && { backgroundColor: theme.colors.todayBackground }]
1466
+ }),
1467
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1468
+ ...slot("columnHeaderDateText", { themed: [theme.text.dayNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }] }),
1363
1469
  allowFontScaling: false,
1364
- children: (0, date_fns.format)(day, (0, _super_calendar_core.weekdayFormatToken)(weekdayFormat), { locale })
1365
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1366
- testID: "column-header-badge",
1367
- style: [
1368
- styles$1.dayHeaderBadge,
1369
- theme.containers.columnHeaderBadge,
1370
- isHighlighted && { backgroundColor: theme.colors.todayBackground }
1371
- ],
1372
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1373
- style: [theme.text.dayNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }],
1374
- allowFontScaling: false,
1375
- ...isToday && { accessibilityLabel: `Today, ${day.getDate()}` },
1376
- children: day.getDate()
1377
- })
1378
- })]
1470
+ children: day.getDate()
1471
+ })
1472
+ })] });
1473
+ return onPressDateHeader ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
1474
+ ...headerSlot,
1475
+ onPress: () => onPressDateHeader(day),
1476
+ accessibilityRole: "button",
1477
+ accessibilityLabel,
1478
+ children: content
1479
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1480
+ ...headerSlot,
1481
+ accessible: true,
1482
+ accessibilityRole: "header",
1483
+ accessibilityLabel,
1484
+ children: content
1379
1485
  });
1380
1486
  };
1381
1487
  const styles$1 = react_native.StyleSheet.create({
@@ -1486,6 +1592,13 @@ function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1486
1592
  const days = (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1487
1593
  return [(0, date_fns.startOfDay)(days[0]), (0, date_fns.endOfDay)(days[days.length - 1])];
1488
1594
  }
1595
+ function expansionRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1596
+ if (mode === "month") return [(0, date_fns.startOfWeek)((0, date_fns.startOfMonth)((0, date_fns.addMonths)(date, -1)), { weekStartsOn }), (0, date_fns.addWeeks)((0, date_fns.endOfWeek)((0, date_fns.endOfMonth)((0, date_fns.addMonths)(date, 1)), { weekStartsOn }), 1)];
1597
+ if (mode === "schedule") return [(0, date_fns.startOfDay)(date), (0, date_fns.endOfDay)((0, date_fns.addMonths)(date, 3))];
1598
+ const days = (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1599
+ const span = days.length;
1600
+ return [(0, date_fns.startOfDay)((0, date_fns.addDays)(days[0], -span)), (0, date_fns.endOfDay)((0, date_fns.addDays)(days[days.length - 1], span))];
1601
+ }
1489
1602
  /**
1490
1603
  * The top-level calendar. Switches between month, week, day, 3days, custom, and
1491
1604
  * schedule modes, and is gesture-driven and virtualized. It is a controlled
@@ -1512,10 +1625,31 @@ function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1512
1625
  * }
1513
1626
  * ```
1514
1627
  */
1515
- 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, weekdayFormat, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventAccessibilityLabel, 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 }) {
1628
+ 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, weekdayFormat, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventAccessibilityLabel, 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, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }) {
1516
1629
  const mergedTheme = (0, react.useMemo)(() => require_MonthList.mergeTheme(theme), [theme]);
1517
1630
  const internalCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
1518
1631
  const cellHeight = cellHeightProp ?? internalCellHeight;
1632
+ const displayEvents = (0, react.useMemo)(() => {
1633
+ let out = events;
1634
+ if (out.some((e) => e.recurrence)) {
1635
+ let [start, end] = expansionRange(mode, date, weekStartsOn, numberOfDays ?? 1, weekEndsOn);
1636
+ if (timeZone) {
1637
+ start = (0, date_fns.addDays)(start, -1);
1638
+ end = (0, date_fns.addDays)(end, 1);
1639
+ }
1640
+ out = (0, _super_calendar_core.expandRecurringEvents)(out, start, end);
1641
+ }
1642
+ if (timeZone) out = (0, _super_calendar_core.eventsInTimeZone)(out, timeZone);
1643
+ return out;
1644
+ }, [
1645
+ events,
1646
+ mode,
1647
+ date.getTime(),
1648
+ weekStartsOn,
1649
+ numberOfDays,
1650
+ weekEndsOn,
1651
+ timeZone
1652
+ ]);
1519
1653
  const handlePressEvent = (0, react.useCallback)((event) => {
1520
1654
  if (!event.disabled) onPressEvent(event);
1521
1655
  }, [onPressEvent]);
@@ -1565,7 +1699,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1565
1699
  value: mergedTheme,
1566
1700
  children: mode === "month" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MonthList.MonthPager, {
1567
1701
  date,
1568
- events,
1702
+ events: displayEvents,
1569
1703
  maxVisibleEventCount,
1570
1704
  weekStartsOn,
1571
1705
  weekdayFormat,
@@ -1589,9 +1723,11 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1589
1723
  onPressMore,
1590
1724
  onChangeDate: handleChangeDate,
1591
1725
  freeSwipe,
1592
- swipeEnabled
1726
+ swipeEnabled,
1727
+ classNames,
1728
+ styles: styleOverrides
1593
1729
  }) : mode === "schedule" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Agenda, {
1594
- events,
1730
+ events: displayEvents,
1595
1731
  locale,
1596
1732
  renderEvent: resolvedRenderEvent,
1597
1733
  keyExtractor,
@@ -1599,13 +1735,15 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1599
1735
  onLongPressEvent: handleLongPressEvent,
1600
1736
  onPressDay,
1601
1737
  activeDate,
1602
- itemSeparatorComponent
1738
+ itemSeparatorComponent,
1739
+ classNames,
1740
+ styles: styleOverrides
1603
1741
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeGrid, {
1604
1742
  mode,
1605
1743
  numberOfDays,
1606
1744
  weekEndsOn,
1607
1745
  date,
1608
- events,
1746
+ events: displayEvents,
1609
1747
  cellHeight,
1610
1748
  hourHeight,
1611
1749
  weekStartsOn,
@@ -1648,17 +1786,23 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1648
1786
  onCreateEvent,
1649
1787
  onPressDateHeader,
1650
1788
  onChangeDate: handleChangeDate,
1651
- renderHeader: renderTimeGridHeader
1789
+ renderHeader: renderTimeGridHeader,
1790
+ classNames,
1791
+ styles: styleOverrides
1652
1792
  })
1653
1793
  });
1654
1794
  }
1655
1795
  //#endregion
1656
1796
  //#region src/components/ResourceTimeline.tsx
1657
1797
  const MOVE_ACTIVATE_MS = 250;
1798
+ const DRAG_ACTIVATE_PX = 8;
1658
1799
  const MINUTES_PER_HOUR = 60;
1800
+ const isWeb = react_native.Platform.OS === "web";
1659
1801
  const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
1660
- function DefaultBar({ event, width }) {
1802
+ const GUTTER_WIDTH = 56;
1803
+ function DefaultBar({ event, width, height }) {
1661
1804
  const theme = require_MonthList.useCalendarTheme();
1805
+ const showTime = height != null ? height > 34 : width > 56;
1662
1806
  const time = (0, _super_calendar_core.eventTimeLabel)({
1663
1807
  mode: "day",
1664
1808
  isAllDay: false,
@@ -1678,7 +1822,7 @@ function DefaultBar({ event, width }) {
1678
1822
  style: [theme.text.eventTitle, { color: theme.colors.eventText }],
1679
1823
  allowFontScaling: false,
1680
1824
  children: event.title
1681
- }), time && width > 56 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1825
+ }), time && showTime ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1682
1826
  numberOfLines: 1,
1683
1827
  style: [styles.barTime, { color: theme.colors.eventText }],
1684
1828
  allowFontScaling: false,
@@ -1686,7 +1830,7 @@ function DefaultBar({ event, width }) {
1686
1830
  }) : null]
1687
1831
  });
1688
1832
  }
1689
- function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Renderer, onPress, onDragEvent, theme }) {
1833
+ function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendererSize, snapMinutes, Renderer, onPress, onLongPress, onDragEvent, theme }) {
1690
1834
  const moveX = (0, react_native_reanimated.useSharedValue)(0);
1691
1835
  const resizeW = (0, react_native_reanimated.useSharedValue)(0);
1692
1836
  const latest = (0, react.useRef)({
@@ -1720,75 +1864,236 @@ function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Rend
1720
1864
  }
1721
1865
  if (handler(event, next.start, next.end) === false) snapBack();
1722
1866
  }, [snapMinutes, snapBack]);
1723
- const barStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
1867
+ const unit = (n) => `${n} minute${n === 1 ? "" : "s"}`;
1868
+ const barActions = draggable ? [
1869
+ {
1870
+ name: "move-later",
1871
+ label: `Move ${unit(snapMinutes)} later`
1872
+ },
1873
+ {
1874
+ name: "move-earlier",
1875
+ label: `Move ${unit(snapMinutes)} earlier`
1876
+ },
1877
+ {
1878
+ name: "extend",
1879
+ label: `Extend by ${unit(snapMinutes)}`
1880
+ },
1881
+ {
1882
+ name: "shrink",
1883
+ label: `Shorten by ${unit(snapMinutes)}`
1884
+ }
1885
+ ] : void 0;
1886
+ const onBarAction = draggable ? (e) => {
1887
+ switch (e.nativeEvent.actionName) {
1888
+ case "move-later":
1889
+ commit(snapMinutes, snapMinutes);
1890
+ break;
1891
+ case "move-earlier":
1892
+ commit(-snapMinutes, -snapMinutes);
1893
+ break;
1894
+ case "extend":
1895
+ commit(0, snapMinutes);
1896
+ break;
1897
+ case "shrink":
1898
+ commit(0, -snapMinutes);
1899
+ break;
1900
+ }
1901
+ } : void 0;
1902
+ const barStyle = (0, react_native_reanimated.useAnimatedStyle)(() => vertical ? {
1903
+ transform: [{ translateY: moveX.value }],
1904
+ height: Math.max(height + resizeW.value, 2)
1905
+ } : {
1724
1906
  transform: [{ translateX: moveX.value }],
1725
1907
  width: Math.max(width + resizeW.value, 2)
1726
- }), [width]);
1908
+ }, [
1909
+ vertical,
1910
+ width,
1911
+ height
1912
+ ]);
1727
1913
  const moveGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(draggable).activateAfterLongPress(MOVE_ACTIVATE_MS).onUpdate((e) => {
1728
- moveX.value = e.translationX;
1914
+ moveX.value = vertical ? e.translationY : e.translationX;
1729
1915
  }).onEnd((e) => {
1730
- const delta = (0, _super_calendar_core.snapDeltaMinutes)(e.translationX, hourWidth, snapMinutes);
1916
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(vertical ? e.translationY : e.translationX, hourSize, snapMinutes);
1731
1917
  if (delta === 0) {
1732
1918
  moveX.value = 0;
1733
1919
  return;
1734
1920
  }
1735
- moveX.value = delta / MINUTES_PER_HOUR * hourWidth;
1921
+ moveX.value = delta / MINUTES_PER_HOUR * hourSize;
1736
1922
  (0, react_native_reanimated.runOnJS)(commit)(delta, delta);
1737
1923
  }), [
1738
1924
  draggable,
1739
- hourWidth,
1925
+ vertical,
1926
+ hourSize,
1740
1927
  snapMinutes,
1741
1928
  moveX,
1742
1929
  commit
1743
1930
  ]);
1744
1931
  const resizeGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(draggable).onUpdate((e) => {
1745
- resizeW.value = e.translationX;
1932
+ resizeW.value = vertical ? e.translationY : e.translationX;
1746
1933
  }).onEnd((e) => {
1747
- const delta = (0, _super_calendar_core.snapDeltaMinutes)(e.translationX, hourWidth, snapMinutes);
1934
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(vertical ? e.translationY : e.translationX, hourSize, snapMinutes);
1748
1935
  if (delta === 0) {
1749
1936
  resizeW.value = 0;
1750
1937
  return;
1751
1938
  }
1752
- resizeW.value = delta / MINUTES_PER_HOUR * hourWidth;
1939
+ resizeW.value = delta / MINUTES_PER_HOUR * hourSize;
1753
1940
  (0, react_native_reanimated.runOnJS)(commit)(0, delta);
1754
1941
  }), [
1755
1942
  draggable,
1756
- hourWidth,
1943
+ vertical,
1944
+ hourSize,
1757
1945
  snapMinutes,
1758
1946
  resizeW,
1759
1947
  commit
1760
1948
  ]);
1761
1949
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
1762
- style: [{
1763
- position: "absolute",
1764
- left,
1765
- top: pe.column * laneHeight,
1766
- height: laneHeight,
1767
- padding: 1
1768
- }, barStyle],
1950
+ style: [
1951
+ {
1952
+ position: "absolute",
1953
+ left,
1954
+ top,
1955
+ padding: 1
1956
+ },
1957
+ vertical ? { width } : { height },
1958
+ barStyle
1959
+ ],
1769
1960
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
1770
1961
  gesture: moveGesture,
1771
1962
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
1772
1963
  onPress,
1964
+ onLongPress,
1773
1965
  accessibilityRole: "button",
1774
1966
  accessibilityLabel: pe.event.title,
1967
+ accessibilityActions: barActions,
1968
+ onAccessibilityAction: onBarAction,
1775
1969
  style: styles.fill,
1776
1970
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
1777
1971
  event: pe.event,
1778
- width,
1972
+ width: rendererSize.width,
1973
+ height: rendererSize.height,
1779
1974
  onPress
1780
1975
  })
1781
1976
  })
1782
1977
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
1783
1978
  gesture: resizeGesture,
1784
1979
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1785
- style: [styles.resizeGrip, { backgroundColor: theme.colors.eventText }],
1786
- accessibilityRole: "adjustable",
1787
- accessibilityLabel: `Resize ${pe.event.title}`
1980
+ testID: "resource-resize-grip",
1981
+ style: [vertical ? styles.resizeGripBottom : styles.resizeGrip, { backgroundColor: theme.colors.eventText }],
1982
+ accessibilityElementsHidden: true,
1983
+ importantForAccessibility: "no"
1788
1984
  })
1789
1985
  })]
1790
1986
  });
1791
1987
  }
1988
+ function LaneInteractionLayer({ resource, vertical, hourSize, startHour, date, snapMinutes, onPressCell, onLongPressCell, onCreateEvent, theme }) {
1989
+ const ghostStart = (0, react_native_reanimated.useSharedValue)(0);
1990
+ const ghostSize = (0, react_native_reanimated.useSharedValue)(0);
1991
+ const ghostVisible = (0, react_native_reanimated.useSharedValue)(0);
1992
+ const timeAt = (0, react.useCallback)((px) => (0, _super_calendar_core.cellRangeFromDrag)(date, px, px, hourSize, startHour, snapMinutes)?.start, [
1993
+ date,
1994
+ hourSize,
1995
+ startHour,
1996
+ snapMinutes
1997
+ ]);
1998
+ const commitCreate = (0, react.useCallback)((fromPx, toPx) => {
1999
+ const range = (0, _super_calendar_core.cellRangeFromDrag)(date, fromPx, toPx, hourSize, startHour, snapMinutes);
2000
+ if (range) onCreateEvent?.(range.start, range.end, resource);
2001
+ }, [
2002
+ date,
2003
+ hourSize,
2004
+ startHour,
2005
+ snapMinutes,
2006
+ onCreateEvent,
2007
+ resource
2008
+ ]);
2009
+ const pressAt = (0, react.useCallback)((px) => {
2010
+ const at = timeAt(px);
2011
+ if (at) onPressCell?.(at, resource);
2012
+ }, [
2013
+ timeAt,
2014
+ onPressCell,
2015
+ resource
2016
+ ]);
2017
+ const laneGesture = (0, react.useMemo)(() => {
2018
+ const pan = onCreateEvent ? react_native_gesture_handler.Gesture.Pan().onStart((e) => {
2019
+ ghostStart.value = vertical ? e.y : e.x;
2020
+ ghostSize.value = 0;
2021
+ ghostVisible.value = 1;
2022
+ }).onUpdate((e) => {
2023
+ ghostSize.value = (vertical ? e.y : e.x) - ghostStart.value;
2024
+ }).onEnd((e, success) => {
2025
+ ghostVisible.value = 0;
2026
+ if (success) (0, react_native_reanimated.runOnJS)(commitCreate)(ghostStart.value, vertical ? e.y : e.x);
2027
+ }).onFinalize(() => {
2028
+ ghostVisible.value = 0;
2029
+ }) : null;
2030
+ const activatedPan = pan ? isWeb ? vertical ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS) : null;
2031
+ const tap = isWeb && onPressCell ? react_native_gesture_handler.Gesture.Tap().onEnd((e) => {
2032
+ (0, react_native_reanimated.runOnJS)(pressAt)(vertical ? e.y : e.x);
2033
+ }) : null;
2034
+ if (activatedPan && tap) return react_native_gesture_handler.Gesture.Exclusive(activatedPan, tap);
2035
+ return activatedPan ?? tap;
2036
+ }, [
2037
+ onCreateEvent,
2038
+ onPressCell,
2039
+ vertical,
2040
+ commitCreate,
2041
+ pressAt,
2042
+ ghostStart,
2043
+ ghostSize,
2044
+ ghostVisible
2045
+ ]);
2046
+ const ghostStyle = (0, react_native_reanimated.useAnimatedStyle)(() => {
2047
+ const stepPx = snapMinutes / MINUTES_PER_HOUR * hourSize;
2048
+ const snap = (v) => stepPx > 0 ? Math.round(v / stepPx) * stepPx : v;
2049
+ const a = snap(ghostStart.value);
2050
+ const b = snap(ghostStart.value + ghostSize.value);
2051
+ const from = Math.min(a, b);
2052
+ const size = Math.max(Math.abs(b - a), 2);
2053
+ return vertical ? {
2054
+ opacity: ghostVisible.value,
2055
+ top: from,
2056
+ height: size
2057
+ } : {
2058
+ opacity: ghostVisible.value,
2059
+ left: from,
2060
+ width: size
2061
+ };
2062
+ }, [
2063
+ vertical,
2064
+ hourSize,
2065
+ snapMinutes
2066
+ ]);
2067
+ const pxOf = (e) => vertical ? e.nativeEvent.locationY : e.nativeEvent.locationX;
2068
+ const handlePress = onPressCell ? (e) => pressAt(pxOf(e)) : void 0;
2069
+ const handleLongPress = onLongPressCell && !onCreateEvent ? (e) => {
2070
+ const at = timeAt(pxOf(e));
2071
+ if (at) onLongPressCell(at, resource);
2072
+ } : void 0;
2073
+ const layer = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
2074
+ testID: "resource-cell-layer",
2075
+ style: react_native.StyleSheet.absoluteFill,
2076
+ onPress: handlePress,
2077
+ onLongPress: handleLongPress,
2078
+ accessibilityElementsHidden: true,
2079
+ importantForAccessibility: "no"
2080
+ });
2081
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [laneGesture ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
2082
+ gesture: laneGesture,
2083
+ children: layer
2084
+ }) : layer, onCreateEvent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
2085
+ testID: "resource-create-ghost",
2086
+ pointerEvents: "none",
2087
+ style: [
2088
+ vertical ? styles.vcreateGhost : styles.hcreateGhost,
2089
+ {
2090
+ backgroundColor: theme.colors.eventBackground,
2091
+ borderColor: theme.colors.todayBackground
2092
+ },
2093
+ ghostStyle
2094
+ ]
2095
+ }) : null] });
2096
+ }
1792
2097
  /**
1793
2098
  * A horizontal resource timeline: rows are resources (rooms, people, machines)
1794
2099
  * and the x-axis is one day's hours. Events sit in their resource's row, and
@@ -1807,9 +2112,11 @@ function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Rend
1807
2112
  * />
1808
2113
  * ```
1809
2114
  */
1810
- function ResourceTimeline({ date, resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, rowHeight = 56, labelWidth = 140, ampm = false, renderEvent, onPressEvent, onDragEvent, dragStepMinutes = 15 }) {
2115
+ function ResourceTimeline({ date, orientation = "horizontal", resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, hourHeight = 48, rowHeight = 56, labelWidth = 140, ampm = false, renderEvent, onPressEvent, onLongPressEvent, onDragEvent, onPressCell, onLongPressCell, onCreateEvent, businessHours, dragStepMinutes = 15 }) {
1811
2116
  const theme = require_MonthList.useCalendarTheme();
1812
2117
  const Renderer = renderEvent ?? DefaultBar;
2118
+ const cellEnabled = !!onPressCell || !!onLongPressCell || !!onCreateEvent;
2119
+ const bandsFor = (resource) => businessHours ? (0, _super_calendar_core.closedHourBands)(date, (d) => businessHours(d, resource), startHour, endHour) : [];
1813
2120
  const hours = (0, react.useMemo)(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
1814
2121
  const trackWidth = (endHour - startHour) * hourWidth;
1815
2122
  const byResource = (0, react.useMemo)(() => {
@@ -1825,6 +2132,127 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
1825
2132
  resourceId,
1826
2133
  date
1827
2134
  ]);
2135
+ if (orientation === "vertical") {
2136
+ const trackHeight = (endHour - startHour) * hourHeight;
2137
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2138
+ style: styles.vroot,
2139
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2140
+ style: [styles.header, { borderBottomColor: theme.colors.gridLine }],
2141
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: { width: GUTTER_WIDTH } }), resources.map((resource) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2142
+ style: [styles.vheaderCell, theme.containers.resourceLabel],
2143
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
2144
+ numberOfLines: 1,
2145
+ style: [styles.vheaderText, { color: theme.colors.text }],
2146
+ allowFontScaling: false,
2147
+ children: resource.title ?? resource.id
2148
+ })
2149
+ }, resource.id))]
2150
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
2151
+ showsVerticalScrollIndicator: true,
2152
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2153
+ style: [styles.vbody, { height: trackHeight }],
2154
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2155
+ style: { width: GUTTER_WIDTH },
2156
+ children: hours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
2157
+ allowFontScaling: false,
2158
+ style: [styles.vhourLabel, {
2159
+ top: Math.max(0, (h - startHour) * hourHeight - 6),
2160
+ color: theme.colors.textMuted
2161
+ }],
2162
+ children: (0, _super_calendar_core.formatHour)(h, { ampm })
2163
+ }, h))
2164
+ }), resources.map((resource) => {
2165
+ const positioned = byResource.get(resource.id) ?? [];
2166
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2167
+ style: [
2168
+ styles.vcolumn,
2169
+ { borderLeftColor: theme.colors.gridLine },
2170
+ theme.containers.resourceRow
2171
+ ],
2172
+ children: [
2173
+ bandsFor(resource).map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2174
+ pointerEvents: "none",
2175
+ testID: "resource-hours-shade",
2176
+ style: [styles.vshadeBand, {
2177
+ top: (b.start - startHour) * hourHeight,
2178
+ height: (b.end - b.start) * hourHeight,
2179
+ backgroundColor: theme.colors.outsideHoursBackground
2180
+ }]
2181
+ }, `shade-${b.start}`)),
2182
+ hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2183
+ pointerEvents: "none",
2184
+ style: [styles.vgridLine, {
2185
+ top: (h - startHour) * hourHeight,
2186
+ backgroundColor: theme.colors.gridLine
2187
+ }]
2188
+ }, h)),
2189
+ cellEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LaneInteractionLayer, {
2190
+ resource,
2191
+ vertical: true,
2192
+ hourSize: hourHeight,
2193
+ startHour,
2194
+ date,
2195
+ snapMinutes: dragStepMinutes,
2196
+ onPressCell,
2197
+ onLongPressCell,
2198
+ onCreateEvent,
2199
+ theme
2200
+ }) : null,
2201
+ positioned.map((pe, idx) => {
2202
+ const top = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourHeight;
2203
+ const bottomPx = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourHeight;
2204
+ const height = Math.max(bottomPx - top, 2);
2205
+ const lanePct = 100 / pe.columns;
2206
+ const left = `${pe.column * lanePct}%`;
2207
+ const width = `${lanePct}%`;
2208
+ const onPress = () => onPressEvent?.(pe.event);
2209
+ if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
2210
+ pe,
2211
+ vertical: true,
2212
+ hourSize: hourHeight,
2213
+ left,
2214
+ top,
2215
+ width,
2216
+ height,
2217
+ rendererSize: {
2218
+ width: 0,
2219
+ height
2220
+ },
2221
+ snapMinutes: dragStepMinutes,
2222
+ Renderer,
2223
+ onPress,
2224
+ onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
2225
+ onDragEvent,
2226
+ theme
2227
+ }, idx);
2228
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
2229
+ onPress,
2230
+ onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
2231
+ accessibilityRole: "button",
2232
+ accessibilityLabel: pe.event.title,
2233
+ style: {
2234
+ position: "absolute",
2235
+ left,
2236
+ width,
2237
+ top,
2238
+ height,
2239
+ padding: 1
2240
+ },
2241
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
2242
+ event: pe.event,
2243
+ width: 0,
2244
+ height,
2245
+ onPress
2246
+ })
2247
+ }, idx);
2248
+ })
2249
+ ]
2250
+ }, resource.id);
2251
+ })]
2252
+ })
2253
+ })]
2254
+ });
2255
+ }
1828
2256
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
1829
2257
  horizontal: true,
1830
2258
  showsHorizontalScrollIndicator: true,
@@ -1875,49 +2303,78 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
1875
2303
  })
1876
2304
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1877
2305
  style: { width: trackWidth },
1878
- children: [hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1879
- pointerEvents: "none",
1880
- style: [styles.gridLine, {
1881
- left: (h - startHour) * hourWidth,
1882
- backgroundColor: theme.colors.gridLine
1883
- }]
1884
- }, h)), positioned.map((pe, idx) => {
1885
- const left = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourWidth;
1886
- const right = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourWidth;
1887
- const width = Math.max(right - left, 2);
1888
- const laneHeight = rowHeight / pe.columns;
1889
- const onPress = () => onPressEvent?.(pe.event);
1890
- if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
1891
- pe,
1892
- left,
1893
- width,
1894
- laneHeight,
1895
- hourWidth,
2306
+ children: [
2307
+ bandsFor(resource).map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2308
+ pointerEvents: "none",
2309
+ testID: "resource-hours-shade",
2310
+ style: [styles.hshadeBand, {
2311
+ left: (b.start - startHour) * hourWidth,
2312
+ width: (b.end - b.start) * hourWidth,
2313
+ backgroundColor: theme.colors.outsideHoursBackground
2314
+ }]
2315
+ }, `shade-${b.start}`)),
2316
+ hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2317
+ pointerEvents: "none",
2318
+ style: [styles.gridLine, {
2319
+ left: (h - startHour) * hourWidth,
2320
+ backgroundColor: theme.colors.gridLine
2321
+ }]
2322
+ }, h)),
2323
+ cellEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LaneInteractionLayer, {
2324
+ resource,
2325
+ vertical: false,
2326
+ hourSize: hourWidth,
2327
+ startHour,
2328
+ date,
1896
2329
  snapMinutes: dragStepMinutes,
1897
- Renderer,
1898
- onPress,
1899
- onDragEvent,
2330
+ onPressCell,
2331
+ onLongPressCell,
2332
+ onCreateEvent,
1900
2333
  theme
1901
- }, idx);
1902
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
1903
- onPress,
1904
- accessibilityRole: "button",
1905
- accessibilityLabel: pe.event.title,
1906
- style: {
1907
- position: "absolute",
2334
+ }) : null,
2335
+ positioned.map((pe, idx) => {
2336
+ const left = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourWidth;
2337
+ const right = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourWidth;
2338
+ const width = Math.max(right - left, 2);
2339
+ const laneHeight = rowHeight / pe.columns;
2340
+ const onPress = () => onPressEvent?.(pe.event);
2341
+ if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
2342
+ pe,
2343
+ vertical: false,
2344
+ hourSize: hourWidth,
1908
2345
  left,
1909
- width,
1910
2346
  top: pe.column * laneHeight,
1911
- height: laneHeight,
1912
- padding: 1
1913
- },
1914
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
1915
- event: pe.event,
1916
2347
  width,
1917
- onPress
1918
- })
1919
- }, idx);
1920
- })]
2348
+ height: laneHeight,
2349
+ rendererSize: { width },
2350
+ snapMinutes: dragStepMinutes,
2351
+ Renderer,
2352
+ onPress,
2353
+ onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
2354
+ onDragEvent,
2355
+ theme
2356
+ }, idx);
2357
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
2358
+ onPress,
2359
+ onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
2360
+ accessibilityRole: "button",
2361
+ accessibilityLabel: pe.event.title,
2362
+ style: {
2363
+ position: "absolute",
2364
+ left,
2365
+ width,
2366
+ top: pe.column * laneHeight,
2367
+ height: laneHeight,
2368
+ padding: 1
2369
+ },
2370
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
2371
+ event: pe.event,
2372
+ width,
2373
+ onPress
2374
+ })
2375
+ }, idx);
2376
+ })
2377
+ ]
1921
2378
  })]
1922
2379
  }, resource.id);
1923
2380
  })]
@@ -1970,6 +2427,71 @@ const styles = react_native.StyleSheet.create({
1970
2427
  width: 4,
1971
2428
  borderRadius: 2,
1972
2429
  opacity: .5
2430
+ },
2431
+ resizeGripBottom: {
2432
+ position: "absolute",
2433
+ bottom: 1,
2434
+ left: "30%",
2435
+ right: "30%",
2436
+ height: 4,
2437
+ borderRadius: 2,
2438
+ opacity: .5
2439
+ },
2440
+ vroot: { flex: 1 },
2441
+ vheaderCell: {
2442
+ flex: 1,
2443
+ paddingVertical: 6,
2444
+ paddingHorizontal: 4,
2445
+ alignItems: "center",
2446
+ borderLeftWidth: react_native.StyleSheet.hairlineWidth
2447
+ },
2448
+ vheaderText: {
2449
+ fontSize: 13,
2450
+ fontWeight: "600"
2451
+ },
2452
+ vbody: { flexDirection: "row" },
2453
+ vcolumn: {
2454
+ flex: 1,
2455
+ borderLeftWidth: react_native.StyleSheet.hairlineWidth
2456
+ },
2457
+ vhourLabel: {
2458
+ position: "absolute",
2459
+ right: 6,
2460
+ fontSize: 10
2461
+ },
2462
+ vgridLine: {
2463
+ position: "absolute",
2464
+ left: 0,
2465
+ right: 0,
2466
+ height: react_native.StyleSheet.hairlineWidth
2467
+ },
2468
+ vcreateGhost: {
2469
+ position: "absolute",
2470
+ left: 2,
2471
+ right: 2,
2472
+ borderWidth: 1,
2473
+ borderRadius: 6,
2474
+ opacity: 0,
2475
+ zIndex: 2
2476
+ },
2477
+ hcreateGhost: {
2478
+ position: "absolute",
2479
+ top: 2,
2480
+ bottom: 2,
2481
+ borderWidth: 1,
2482
+ borderRadius: 6,
2483
+ opacity: 0,
2484
+ zIndex: 2
2485
+ },
2486
+ hshadeBand: {
2487
+ position: "absolute",
2488
+ top: 0,
2489
+ bottom: 0
2490
+ },
2491
+ vshadeBand: {
2492
+ position: "absolute",
2493
+ left: 0,
2494
+ right: 0
1973
2495
  }
1974
2496
  });
1975
2497
  //#endregion
@@ -2089,6 +2611,18 @@ Object.defineProperty(exports, "nextDateRange", {
2089
2611
  return _super_calendar_core.nextDateRange;
2090
2612
  }
2091
2613
  });
2614
+ Object.defineProperty(exports, "parseICalendar", {
2615
+ enumerable: true,
2616
+ get: function() {
2617
+ return _super_calendar_core.parseICalendar;
2618
+ }
2619
+ });
2620
+ Object.defineProperty(exports, "toICalendar", {
2621
+ enumerable: true,
2622
+ get: function() {
2623
+ return _super_calendar_core.toICalendar;
2624
+ }
2625
+ });
2092
2626
  Object.defineProperty(exports, "toZonedTime", {
2093
2627
  enumerable: true,
2094
2628
  get: function() {