@super-calendar/native 2.3.2 → 2.4.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,
@@ -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);
@@ -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);
@@ -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);
@@ -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;
@@ -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 ? [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 ? 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,7 +1786,9 @@ 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
  }
@@ -1657,8 +1797,10 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1657
1797
  const MOVE_ACTIVATE_MS = 250;
1658
1798
  const MINUTES_PER_HOUR = 60;
1659
1799
  const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
1660
- function DefaultBar({ event, width }) {
1800
+ const GUTTER_WIDTH = 56;
1801
+ function DefaultBar({ event, width, height }) {
1661
1802
  const theme = require_MonthList.useCalendarTheme();
1803
+ const showTime = height != null ? height > 34 : width > 56;
1662
1804
  const time = (0, _super_calendar_core.eventTimeLabel)({
1663
1805
  mode: "day",
1664
1806
  isAllDay: false,
@@ -1678,7 +1820,7 @@ function DefaultBar({ event, width }) {
1678
1820
  style: [theme.text.eventTitle, { color: theme.colors.eventText }],
1679
1821
  allowFontScaling: false,
1680
1822
  children: event.title
1681
- }), time && width > 56 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1823
+ }), time && showTime ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1682
1824
  numberOfLines: 1,
1683
1825
  style: [styles.barTime, { color: theme.colors.eventText }],
1684
1826
  allowFontScaling: false,
@@ -1686,7 +1828,7 @@ function DefaultBar({ event, width }) {
1686
1828
  }) : null]
1687
1829
  });
1688
1830
  }
1689
- function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Renderer, onPress, onDragEvent, theme }) {
1831
+ function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendererSize, snapMinutes, Renderer, onPress, onDragEvent, theme }) {
1690
1832
  const moveX = (0, react_native_reanimated.useSharedValue)(0);
1691
1833
  const resizeW = (0, react_native_reanimated.useSharedValue)(0);
1692
1834
  const latest = (0, react.useRef)({
@@ -1720,71 +1862,122 @@ function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Rend
1720
1862
  }
1721
1863
  if (handler(event, next.start, next.end) === false) snapBack();
1722
1864
  }, [snapMinutes, snapBack]);
1723
- const barStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
1865
+ const unit = (n) => `${n} minute${n === 1 ? "" : "s"}`;
1866
+ const barActions = draggable ? [
1867
+ {
1868
+ name: "move-later",
1869
+ label: `Move ${unit(snapMinutes)} later`
1870
+ },
1871
+ {
1872
+ name: "move-earlier",
1873
+ label: `Move ${unit(snapMinutes)} earlier`
1874
+ },
1875
+ {
1876
+ name: "extend",
1877
+ label: `Extend by ${unit(snapMinutes)}`
1878
+ },
1879
+ {
1880
+ name: "shrink",
1881
+ label: `Shorten by ${unit(snapMinutes)}`
1882
+ }
1883
+ ] : void 0;
1884
+ const onBarAction = draggable ? (e) => {
1885
+ switch (e.nativeEvent.actionName) {
1886
+ case "move-later":
1887
+ commit(snapMinutes, snapMinutes);
1888
+ break;
1889
+ case "move-earlier":
1890
+ commit(-snapMinutes, -snapMinutes);
1891
+ break;
1892
+ case "extend":
1893
+ commit(0, snapMinutes);
1894
+ break;
1895
+ case "shrink":
1896
+ commit(0, -snapMinutes);
1897
+ break;
1898
+ }
1899
+ } : void 0;
1900
+ const barStyle = (0, react_native_reanimated.useAnimatedStyle)(() => vertical ? {
1901
+ transform: [{ translateY: moveX.value }],
1902
+ height: Math.max(height + resizeW.value, 2)
1903
+ } : {
1724
1904
  transform: [{ translateX: moveX.value }],
1725
1905
  width: Math.max(width + resizeW.value, 2)
1726
- }), [width]);
1906
+ }, [
1907
+ vertical,
1908
+ width,
1909
+ height
1910
+ ]);
1727
1911
  const moveGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(draggable).activateAfterLongPress(MOVE_ACTIVATE_MS).onUpdate((e) => {
1728
- moveX.value = e.translationX;
1912
+ moveX.value = vertical ? e.translationY : e.translationX;
1729
1913
  }).onEnd((e) => {
1730
- const delta = (0, _super_calendar_core.snapDeltaMinutes)(e.translationX, hourWidth, snapMinutes);
1914
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(vertical ? e.translationY : e.translationX, hourSize, snapMinutes);
1731
1915
  if (delta === 0) {
1732
1916
  moveX.value = 0;
1733
1917
  return;
1734
1918
  }
1735
- moveX.value = delta / MINUTES_PER_HOUR * hourWidth;
1919
+ moveX.value = delta / MINUTES_PER_HOUR * hourSize;
1736
1920
  (0, react_native_reanimated.runOnJS)(commit)(delta, delta);
1737
1921
  }), [
1738
1922
  draggable,
1739
- hourWidth,
1923
+ vertical,
1924
+ hourSize,
1740
1925
  snapMinutes,
1741
1926
  moveX,
1742
1927
  commit
1743
1928
  ]);
1744
1929
  const resizeGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(draggable).onUpdate((e) => {
1745
- resizeW.value = e.translationX;
1930
+ resizeW.value = vertical ? e.translationY : e.translationX;
1746
1931
  }).onEnd((e) => {
1747
- const delta = (0, _super_calendar_core.snapDeltaMinutes)(e.translationX, hourWidth, snapMinutes);
1932
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(vertical ? e.translationY : e.translationX, hourSize, snapMinutes);
1748
1933
  if (delta === 0) {
1749
1934
  resizeW.value = 0;
1750
1935
  return;
1751
1936
  }
1752
- resizeW.value = delta / MINUTES_PER_HOUR * hourWidth;
1937
+ resizeW.value = delta / MINUTES_PER_HOUR * hourSize;
1753
1938
  (0, react_native_reanimated.runOnJS)(commit)(0, delta);
1754
1939
  }), [
1755
1940
  draggable,
1756
- hourWidth,
1941
+ vertical,
1942
+ hourSize,
1757
1943
  snapMinutes,
1758
1944
  resizeW,
1759
1945
  commit
1760
1946
  ]);
1761
1947
  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],
1948
+ style: [
1949
+ {
1950
+ position: "absolute",
1951
+ left,
1952
+ top,
1953
+ padding: 1
1954
+ },
1955
+ vertical ? { width } : { height },
1956
+ barStyle
1957
+ ],
1769
1958
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
1770
1959
  gesture: moveGesture,
1771
1960
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
1772
1961
  onPress,
1773
1962
  accessibilityRole: "button",
1774
1963
  accessibilityLabel: pe.event.title,
1964
+ accessibilityActions: barActions,
1965
+ onAccessibilityAction: onBarAction,
1775
1966
  style: styles.fill,
1776
1967
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
1777
1968
  event: pe.event,
1778
- width,
1969
+ width: rendererSize.width,
1970
+ height: rendererSize.height,
1779
1971
  onPress
1780
1972
  })
1781
1973
  })
1782
1974
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
1783
1975
  gesture: resizeGesture,
1784
1976
  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}`
1977
+ testID: "resource-resize-grip",
1978
+ style: [vertical ? styles.resizeGripBottom : styles.resizeGrip, { backgroundColor: theme.colors.eventText }],
1979
+ accessibilityElementsHidden: true,
1980
+ importantForAccessibility: "no"
1788
1981
  })
1789
1982
  })]
1790
1983
  });
@@ -1807,7 +2000,7 @@ function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Rend
1807
2000
  * />
1808
2001
  * ```
1809
2002
  */
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 }) {
2003
+ 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, onDragEvent, dragStepMinutes = 15 }) {
1811
2004
  const theme = require_MonthList.useCalendarTheme();
1812
2005
  const Renderer = renderEvent ?? DefaultBar;
1813
2006
  const hours = (0, react.useMemo)(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
@@ -1825,6 +2018,101 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
1825
2018
  resourceId,
1826
2019
  date
1827
2020
  ]);
2021
+ if (orientation === "vertical") {
2022
+ const trackHeight = (endHour - startHour) * hourHeight;
2023
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2024
+ style: styles.vroot,
2025
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2026
+ style: [styles.header, { borderBottomColor: theme.colors.gridLine }],
2027
+ 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, {
2028
+ style: [styles.vheaderCell, theme.containers.resourceLabel],
2029
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
2030
+ numberOfLines: 1,
2031
+ style: [styles.vheaderText, { color: theme.colors.text }],
2032
+ allowFontScaling: false,
2033
+ children: resource.title ?? resource.id
2034
+ })
2035
+ }, resource.id))]
2036
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
2037
+ showsVerticalScrollIndicator: true,
2038
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2039
+ style: [styles.vbody, { height: trackHeight }],
2040
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2041
+ style: { width: GUTTER_WIDTH },
2042
+ children: hours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
2043
+ allowFontScaling: false,
2044
+ style: [styles.vhourLabel, {
2045
+ top: Math.max(0, (h - startHour) * hourHeight - 6),
2046
+ color: theme.colors.textMuted
2047
+ }],
2048
+ children: (0, _super_calendar_core.formatHour)(h, { ampm })
2049
+ }, h))
2050
+ }), resources.map((resource) => {
2051
+ const positioned = byResource.get(resource.id) ?? [];
2052
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
2053
+ style: [
2054
+ styles.vcolumn,
2055
+ { borderLeftColor: theme.colors.gridLine },
2056
+ theme.containers.resourceRow
2057
+ ],
2058
+ children: [hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
2059
+ pointerEvents: "none",
2060
+ style: [styles.vgridLine, {
2061
+ top: (h - startHour) * hourHeight,
2062
+ backgroundColor: theme.colors.gridLine
2063
+ }]
2064
+ }, h)), positioned.map((pe, idx) => {
2065
+ const top = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourHeight;
2066
+ const bottomPx = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourHeight;
2067
+ const height = Math.max(bottomPx - top, 2);
2068
+ const lanePct = 100 / pe.columns;
2069
+ const left = `${pe.column * lanePct}%`;
2070
+ const width = `${lanePct}%`;
2071
+ const onPress = () => onPressEvent?.(pe.event);
2072
+ if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
2073
+ pe,
2074
+ vertical: true,
2075
+ hourSize: hourHeight,
2076
+ left,
2077
+ top,
2078
+ width,
2079
+ height,
2080
+ rendererSize: {
2081
+ width: 0,
2082
+ height
2083
+ },
2084
+ snapMinutes: dragStepMinutes,
2085
+ Renderer,
2086
+ onPress,
2087
+ onDragEvent,
2088
+ theme
2089
+ }, idx);
2090
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
2091
+ onPress,
2092
+ accessibilityRole: "button",
2093
+ accessibilityLabel: pe.event.title,
2094
+ style: {
2095
+ position: "absolute",
2096
+ left,
2097
+ width,
2098
+ top,
2099
+ height,
2100
+ padding: 1
2101
+ },
2102
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
2103
+ event: pe.event,
2104
+ width: 0,
2105
+ height,
2106
+ onPress
2107
+ })
2108
+ }, idx);
2109
+ })]
2110
+ }, resource.id);
2111
+ })]
2112
+ })
2113
+ })]
2114
+ });
2115
+ }
1828
2116
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
1829
2117
  horizontal: true,
1830
2118
  showsHorizontalScrollIndicator: true,
@@ -1889,10 +2177,13 @@ function ResourceTimeline({ date, resources, events, resourceId = (event) => eve
1889
2177
  const onPress = () => onPressEvent?.(pe.event);
1890
2178
  if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
1891
2179
  pe,
2180
+ vertical: false,
2181
+ hourSize: hourWidth,
1892
2182
  left,
2183
+ top: pe.column * laneHeight,
1893
2184
  width,
1894
- laneHeight,
1895
- hourWidth,
2185
+ height: laneHeight,
2186
+ rendererSize: { width },
1896
2187
  snapMinutes: dragStepMinutes,
1897
2188
  Renderer,
1898
2189
  onPress,
@@ -1970,6 +2261,43 @@ const styles = react_native.StyleSheet.create({
1970
2261
  width: 4,
1971
2262
  borderRadius: 2,
1972
2263
  opacity: .5
2264
+ },
2265
+ resizeGripBottom: {
2266
+ position: "absolute",
2267
+ bottom: 1,
2268
+ left: "30%",
2269
+ right: "30%",
2270
+ height: 4,
2271
+ borderRadius: 2,
2272
+ opacity: .5
2273
+ },
2274
+ vroot: { flex: 1 },
2275
+ vheaderCell: {
2276
+ flex: 1,
2277
+ paddingVertical: 6,
2278
+ paddingHorizontal: 4,
2279
+ alignItems: "center",
2280
+ borderLeftWidth: react_native.StyleSheet.hairlineWidth
2281
+ },
2282
+ vheaderText: {
2283
+ fontSize: 13,
2284
+ fontWeight: "600"
2285
+ },
2286
+ vbody: { flexDirection: "row" },
2287
+ vcolumn: {
2288
+ flex: 1,
2289
+ borderLeftWidth: react_native.StyleSheet.hairlineWidth
2290
+ },
2291
+ vhourLabel: {
2292
+ position: "absolute",
2293
+ right: 6,
2294
+ fontSize: 10
2295
+ },
2296
+ vgridLine: {
2297
+ position: "absolute",
2298
+ left: 0,
2299
+ right: 0,
2300
+ height: react_native.StyleSheet.hairlineWidth
1973
2301
  }
1974
2302
  });
1975
2303
  //#endregion
@@ -2089,6 +2417,18 @@ Object.defineProperty(exports, "nextDateRange", {
2089
2417
  return _super_calendar_core.nextDateRange;
2090
2418
  }
2091
2419
  });
2420
+ Object.defineProperty(exports, "parseICalendar", {
2421
+ enumerable: true,
2422
+ get: function() {
2423
+ return _super_calendar_core.parseICalendar;
2424
+ }
2425
+ });
2426
+ Object.defineProperty(exports, "toICalendar", {
2427
+ enumerable: true,
2428
+ get: function() {
2429
+ return _super_calendar_core.toICalendar;
2430
+ }
2431
+ });
2092
2432
  Object.defineProperty(exports, "toZonedTime", {
2093
2433
  enumerable: true,
2094
2434
  get: function() {