@super-calendar/native 2.1.5 → 2.3.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.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { a as useWebPagerKeys, c as defaultTheme, i as MonthView, l as mergeTheme, n as DefaultMonthEvent, o as CalendarThemeProvider, r as MonthPager, s as darkTheme, t as MonthList, u as useCalendarTheme } from "./MonthList-BKlLes2B.mjs";
1
+ import { a as withEventAccessibilityLabel, c as darkTheme, d as useCalendarTheme, i as MonthView, l as defaultTheme, n as DefaultMonthEvent, o as useWebPagerKeys, r as MonthPager, s as CalendarThemeProvider, t as MonthList, u as mergeTheme } from "./MonthList-BidXJMfm.mjs";
2
2
  import { addDays, differenceInCalendarDays, endOfDay, endOfMonth, endOfWeek, format, getHours, getISOWeek, getMinutes, isSameDay, startOfDay, startOfMonth, startOfWeek } from "date-fns";
3
3
  import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import Animated, { runOnJS, scrollTo, useAnimatedReaction, useAnimatedRef, useAnimatedScrollHandler, useAnimatedStyle, useDerivedValue, useSharedValue } from "react-native-reanimated";
5
- import { buildMonthGrid, buildMonthWeeks, cellRangeFromDrag, closedHourBands, daySelectionState, eventAccessibilityLabel, eventChipLayout, eventTimeLabel, eventsInTimeZone, expandRecurringEvents, formatHour, getIsToday, getIsToday as getIsToday$1, getViewDays, getViewDays as getViewDays$1, getWeekDays, isAllDayEvent, isAllDayEvent as isAllDayEvent$1, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isSameCalendarDay as isSameCalendarDay$1, isWeekend, isWeekend as isWeekend$1, isWithinDateRange, layoutDayEvents, layoutDayEvents as layoutDayEvents$1, minutesIntoDay, nextDateRange, resolveDraggedBounds, snapDeltaMinutes, titleEllipsizeMode, titleNumberOfLines, toZonedTime, useDateRange, useMonthGrid, viewDayCount } from "@super-calendar/core";
5
+ import { buildMonthGrid, buildMonthWeeks, cellRangeFromDrag, closedHourBands, daySelectionState, eventAccessibilityLabel, eventChipLayout, eventTimeLabel, eventsInTimeZone, expandRecurringEvents, formatHour, getIsToday, getIsToday as getIsToday$1, getViewDays, getViewDays as getViewDays$1, getWeekDays, isAllDayEvent, isAllDayEvent as isAllDayEvent$1, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isSameCalendarDay as isSameCalendarDay$1, isWeekend, isWeekend as isWeekend$1, isWithinDateRange, layoutDayEvents, layoutDayEvents as layoutDayEvents$1, minutesIntoDay, nextDateRange, resolveDraggedBounds, snapDeltaMinutes, titleEllipsizeMode, titleNumberOfLines, toZonedTime, useDateRange, useMonthGrid, viewDayCount, weekdayFormatToken, weekdayFormatToken as weekdayFormatToken$1 } from "@super-calendar/core";
6
6
  import { LegendList } from "@legendapp/list/react-native";
7
- import { Platform, Pressable, StyleSheet, Text, TouchableOpacity, View, useWindowDimensions } from "react-native";
7
+ import { Platform, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View, useWindowDimensions } from "react-native";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Gesture, GestureDetector } from "react-native-gesture-handler";
10
10
  //#region src/components/Agenda.tsx
@@ -43,14 +43,14 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
43
43
  if (item.kind === "header") {
44
44
  const isHighlighted = activeDate ? isSameDay(item.date, activeDate) : getIsToday$1(item.date);
45
45
  return /* @__PURE__ */ jsx(Text, {
46
- style: [styles$3.header, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }],
46
+ style: [styles$4.header, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }],
47
47
  onPress: onPressDay ? () => onPressDay(item.date) : void 0,
48
48
  accessibilityRole: onPressDay ? "button" : "header",
49
49
  children: format(item.date, "EEEE, d LLLL", { locale })
50
50
  });
51
51
  }
52
52
  return /* @__PURE__ */ jsx(View, {
53
- style: styles$3.eventRow,
53
+ style: [styles$4.eventRow, theme.containers.agendaRow],
54
54
  children: /* @__PURE__ */ jsx(RenderEventComponent, {
55
55
  event: item.event,
56
56
  mode: "schedule",
@@ -69,11 +69,11 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
69
69
  RenderEventComponent
70
70
  ]);
71
71
  if (rows.length === 0) return /* @__PURE__ */ jsx(Text, {
72
- style: [styles$3.empty, { color: theme.colors.textMuted }],
72
+ style: [styles$4.empty, { color: theme.colors.textMuted }],
73
73
  children: "No events"
74
74
  });
75
75
  return /* @__PURE__ */ jsx(LegendList, {
76
- style: styles$3.list,
76
+ style: [styles$4.list, theme.containers.agendaList],
77
77
  data: rows,
78
78
  keyExtractor: keyExtractorRow,
79
79
  renderItem,
@@ -81,7 +81,7 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
81
81
  recycleItems: false
82
82
  });
83
83
  }
84
- const styles$3 = StyleSheet.create({
84
+ const styles$4 = StyleSheet.create({
85
85
  list: { flex: 1 },
86
86
  header: {
87
87
  fontSize: 13,
@@ -114,7 +114,7 @@ const numericStyle = (value, fallback) => typeof value === "number" ? value : fa
114
114
  * only shows once a full line is free beneath the title. Pass your own
115
115
  * `renderEvent` to `<Calendar>` to replace it entirely.
116
116
  */
117
- function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, cellStyle, onPress, onLongPress }) {
117
+ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, accessibilityLabel: accessibilityLabelProp, cellStyle, onPress, onLongPress }) {
118
118
  const theme = useCalendarTheme();
119
119
  const isAllDayEvent = isAllDay ?? false;
120
120
  const timeLabel = eventTimeLabel({
@@ -128,7 +128,7 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
128
128
  });
129
129
  const ellipsizeMode = titleEllipsizeMode(ellipsizeTitle);
130
130
  const titleLineHeight = numericStyle(theme.text.eventTitle.lineHeight, FALLBACK_TITLE_LINE_HEIGHT);
131
- const accessibilityLabel = eventAccessibilityLabel({
131
+ const accessibilityLabel = accessibilityLabelProp ?? eventAccessibilityLabel({
132
132
  title: event.title,
133
133
  isAllDay: isAllDayEvent,
134
134
  start: event.start,
@@ -158,12 +158,16 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
158
158
  const timeStyle = useAnimatedStyle(() => {
159
159
  return { display: layout.value.showTime ? "flex" : "none" };
160
160
  }, [layout]);
161
- return /* @__PURE__ */ jsxs(TouchableOpacity, {
161
+ const contentStyle = useAnimatedStyle(() => {
162
+ const { titleMaxLines, showTime } = layout.value;
163
+ return { justifyContent: titleMaxLines === 1 && !showTime ? "center" : "flex-start" };
164
+ }, [layout]);
165
+ return /* @__PURE__ */ jsx(TouchableOpacity, {
162
166
  style: [
163
- styles$2.box,
164
- isSchedule && styles$2.scheduleBox,
167
+ styles$3.box,
168
+ isSchedule && styles$3.scheduleBox,
165
169
  { backgroundColor: theme.colors.eventBackground },
166
- event.disabled && styles$2.disabled,
170
+ event.disabled && styles$3.disabled,
167
171
  cellStyle
168
172
  ],
169
173
  onPress,
@@ -172,46 +176,50 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
172
176
  accessibilityRole: "button",
173
177
  accessibilityLabel,
174
178
  accessibilityState: { disabled: event.disabled ?? false },
175
- children: [event.title ? fixedTitleLines == null ? /* @__PURE__ */ jsx(Animated.View, {
176
- style: [styles$2.titleClip, titleClipStyle],
177
- children: /* @__PURE__ */ jsx(Text, {
179
+ children: /* @__PURE__ */ jsxs(Animated.View, {
180
+ testID: "event-chip-content",
181
+ style: [styles$3.content, contentStyle],
182
+ children: [event.title ? fixedTitleLines == null ? /* @__PURE__ */ jsx(Animated.View, {
183
+ style: [styles$3.titleClip, titleClipStyle],
184
+ children: /* @__PURE__ */ jsx(Text, {
185
+ style: [
186
+ theme.text.eventTitle,
187
+ isSchedule && styles$3.scheduleTitle,
188
+ { color: theme.colors.eventText }
189
+ ],
190
+ ellipsizeMode,
191
+ allowFontScaling: false,
192
+ children: event.title
193
+ })
194
+ }) : /* @__PURE__ */ jsx(Text, {
178
195
  style: [
179
196
  theme.text.eventTitle,
180
- isSchedule && styles$2.scheduleTitle,
197
+ styles$3.title,
198
+ isSchedule && styles$3.scheduleTitle,
181
199
  { color: theme.colors.eventText }
182
200
  ],
201
+ numberOfLines: fixedTitleLines,
183
202
  ellipsizeMode,
184
203
  allowFontScaling: false,
185
204
  children: event.title
186
- })
187
- }) : /* @__PURE__ */ jsx(Text, {
188
- style: [
189
- theme.text.eventTitle,
190
- styles$2.title,
191
- isSchedule && styles$2.scheduleTitle,
192
- { color: theme.colors.eventText }
193
- ],
194
- numberOfLines: fixedTitleLines,
195
- ellipsizeMode,
196
- allowFontScaling: false,
197
- children: event.title
198
- }) : null, timeLabel ? /* @__PURE__ */ jsx(Animated.View, {
199
- style: timeStyle,
200
- children: /* @__PURE__ */ jsx(Text, {
201
- style: [
202
- styles$2.time,
203
- isSchedule && styles$2.scheduleTime,
204
- { color: theme.colors.eventText }
205
- ],
206
- numberOfLines: 2,
207
- ellipsizeMode,
208
- allowFontScaling: false,
209
- children: timeLabel
210
- })
211
- }) : null]
205
+ }) : null, timeLabel ? /* @__PURE__ */ jsx(Animated.View, {
206
+ style: timeStyle,
207
+ children: /* @__PURE__ */ jsx(Text, {
208
+ style: [
209
+ styles$3.time,
210
+ isSchedule && styles$3.scheduleTime,
211
+ { color: theme.colors.eventText }
212
+ ],
213
+ numberOfLines: 2,
214
+ ellipsizeMode,
215
+ allowFontScaling: false,
216
+ children: timeLabel
217
+ })
218
+ }) : null]
219
+ })
212
220
  });
213
221
  }
214
- const styles$2 = StyleSheet.create({
222
+ const styles$3 = StyleSheet.create({
215
223
  box: {
216
224
  flexGrow: 1,
217
225
  flexShrink: 1,
@@ -236,6 +244,10 @@ const styles$2 = StyleSheet.create({
236
244
  lineHeight: 18,
237
245
  opacity: .75
238
246
  },
247
+ content: {
248
+ flexGrow: 1,
249
+ flexShrink: 1
250
+ },
239
251
  titleClip: { overflow: "hidden" },
240
252
  title: { flexShrink: 1 },
241
253
  time: {
@@ -295,18 +307,26 @@ function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent
295
307
  });
296
308
  if (perDay.every((list) => list.length === 0)) return null;
297
309
  return /* @__PURE__ */ jsxs(View, {
298
- style: [styles$1.lane, { borderBottomColor: theme.colors.gridLine }],
310
+ style: [
311
+ styles$2.lane,
312
+ { borderBottomColor: theme.colors.gridLine },
313
+ theme.containers.allDayLane
314
+ ],
299
315
  children: [/* @__PURE__ */ jsx(View, {
300
- style: [styles$1.gutter, { width: hourColumnWidth }],
316
+ style: [styles$2.gutter, { width: hourColumnWidth }],
301
317
  children: /* @__PURE__ */ jsx(Text, {
302
- style: [styles$1.label, { color: theme.colors.textMuted }],
318
+ style: [styles$2.label, { color: theme.colors.textMuted }],
303
319
  allowFontScaling: false,
304
320
  children: "all-day"
305
321
  })
306
322
  }), days.map((day, dayIndex) => /* @__PURE__ */ jsx(View, {
307
- style: [styles$1.column, { width: dayWidth }],
323
+ style: [
324
+ styles$2.column,
325
+ { width: dayWidth },
326
+ theme.containers.allDayColumn
327
+ ],
308
328
  children: perDay[dayIndex].map((event, index) => /* @__PURE__ */ jsx(View, {
309
- style: styles$1.chip,
329
+ style: styles$2.chip,
310
330
  children: /* @__PURE__ */ jsx(RenderEventComponent, {
311
331
  event,
312
332
  mode,
@@ -318,7 +338,7 @@ function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent
318
338
  }, day.toISOString()))]
319
339
  });
320
340
  }
321
- const styles$1 = StyleSheet.create({
341
+ const styles$2 = StyleSheet.create({
322
342
  lane: {
323
343
  flexDirection: "row",
324
344
  borderBottomWidth: StyleSheet.hairlineWidth
@@ -339,9 +359,9 @@ const styles$1 = StyleSheet.create({
339
359
  //#endregion
340
360
  //#region src/components/TimeGrid.tsx
341
361
  const isWeb = Platform.OS === "web";
342
- const MINUTES_PER_HOUR = 60;
362
+ const MINUTES_PER_HOUR$1 = 60;
343
363
  const HOURS_PER_DAY = 24;
344
- const MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
364
+ const MINUTES_PER_DAY = MINUTES_PER_HOUR$1 * HOURS_PER_DAY;
345
365
  const PAGE_WINDOW = 180;
346
366
  const PAGE_VIEWABILITY = { itemVisiblePercentThreshold: 90 };
347
367
  /** Default height in pixels of one hour row on the time grid. */
@@ -352,7 +372,7 @@ const DEFAULT_HOUR_COLUMN_WIDTH = 56;
352
372
  const MIN_EVENT_HEIGHT = 32;
353
373
  const EVENT_GAP = 2;
354
374
  const DRAG_ACTIVATE_MS = 300;
355
- const MOVE_ACTIVATE_MS = 500;
375
+ const MOVE_ACTIVATE_MS$1 = 500;
356
376
  const DRAG_ACTIVATE_PX = 8;
357
377
  const RESIZE_HANDLE_HEIGHT = 14;
358
378
  const DEFAULT_DRAG_STEP_MINUTES = 15;
@@ -446,12 +466,12 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
446
466
  moveOffsetX.value = 0;
447
467
  return;
448
468
  }
449
- moveOffset.value = minuteDelta / MINUTES_PER_HOUR * cellHeight.value;
469
+ moveOffset.value = minuteDelta / MINUTES_PER_HOUR$1 * cellHeight.value;
450
470
  moveOffsetX.value = dayDelta * dayWidth;
451
471
  const totalDelta = minuteDelta + dayDelta * MINUTES_PER_DAY;
452
472
  runOnJS(commitDrag)(totalDelta, totalDelta);
453
473
  });
454
- return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS);
474
+ return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS$1);
455
475
  }, [
456
476
  draggable,
457
477
  snapMinutes,
@@ -474,7 +494,7 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
474
494
  resizeDelta.value = 0;
475
495
  return;
476
496
  }
477
- resizeDelta.value = delta / MINUTES_PER_HOUR * cellHeight.value;
497
+ resizeDelta.value = delta / MINUTES_PER_HOUR$1 * cellHeight.value;
478
498
  runOnJS(commitDrag)(0, delta);
479
499
  }), [
480
500
  resizable,
@@ -488,12 +508,13 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
488
508
  const handleLongPress = !draggable && onLongPress ? () => onLongPress(positioned.event) : void 0;
489
509
  const box = /* @__PURE__ */ jsxs(Animated.View, {
490
510
  style: [
491
- styles.eventBox,
511
+ styles$1.eventBox,
492
512
  {
493
513
  left,
494
514
  width
495
515
  },
496
- boxStyle
516
+ boxStyle,
517
+ theme.containers.timeGridEvent
497
518
  ],
498
519
  children: [/* @__PURE__ */ jsx(RenderEventComponent, {
499
520
  event: positioned.event,
@@ -506,8 +527,8 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
506
527
  }), resizable ? /* @__PURE__ */ jsx(GestureDetector, {
507
528
  gesture: resizeGesture,
508
529
  children: /* @__PURE__ */ jsx(Animated.View, {
509
- style: styles.resizeHandle,
510
- children: showDragHandle ? /* @__PURE__ */ jsx(View, { style: [styles.resizeGrip, { backgroundColor: theme.colors.eventText }] }) : null
530
+ style: styles$1.resizeHandle,
531
+ children: showDragHandle ? /* @__PURE__ */ jsx(View, { style: [styles$1.resizeGrip, { backgroundColor: theme.colors.eventText }] }) : null
511
532
  })
512
533
  }) : null]
513
534
  });
@@ -522,8 +543,8 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
522
543
  const animatedStyle = useAnimatedStyle(() => ({ top: (hour - minHour) * cellHeight.value }), [hour, minHour]);
523
544
  return /* @__PURE__ */ jsxs(Animated.View, {
524
545
  style: [
525
- styles.hourRow,
526
- styles.nonInteractive,
546
+ styles$1.hourRow,
547
+ styles$1.nonInteractive,
527
548
  animatedStyle
528
549
  ],
529
550
  children: [hourComponent ? /* @__PURE__ */ jsx(View, {
@@ -532,7 +553,7 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
532
553
  }) : /* @__PURE__ */ jsx(Text, {
533
554
  style: [
534
555
  theme.text.hourLabel,
535
- styles.hourLabel,
556
+ styles$1.hourLabel,
536
557
  {
537
558
  width: hourColumnWidth,
538
559
  color: theme.colors.textMuted
@@ -540,7 +561,7 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
540
561
  ],
541
562
  allowFontScaling: false,
542
563
  children: label
543
- }), /* @__PURE__ */ jsx(View, { style: [styles.hourLine, { backgroundColor: theme.colors.gridLine }] })]
564
+ }), /* @__PURE__ */ jsx(View, { style: [styles$1.hourLine, { backgroundColor: theme.colors.gridLine }] })]
544
565
  });
545
566
  };
546
567
  const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth }) => {
@@ -551,8 +572,8 @@ const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth })
551
572
  fraction
552
573
  ]);
553
574
  return /* @__PURE__ */ jsx(Animated.View, { style: [
554
- styles.timeslotLine,
555
- styles.nonInteractive,
575
+ styles$1.timeslotLine,
576
+ styles$1.nonInteractive,
556
577
  {
557
578
  left: hourColumnWidth,
558
579
  backgroundColor: theme.colors.gridLine
@@ -561,16 +582,18 @@ const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth })
561
582
  ] });
562
583
  };
563
584
  const NowIndicator = ({ cellHeight, nowHours, minHour, left, width, color }) => {
585
+ const theme = useCalendarTheme();
564
586
  const animatedStyle = useAnimatedStyle(() => ({ top: (nowHours - minHour) * cellHeight.value }), [nowHours, minHour]);
565
587
  return /* @__PURE__ */ jsx(Animated.View, { style: [
566
- styles.nowIndicator,
567
- styles.nonInteractive,
588
+ styles$1.nowIndicator,
589
+ styles$1.nonInteractive,
568
590
  {
569
591
  left,
570
592
  width,
571
593
  backgroundColor: color
572
594
  },
573
- animatedStyle
595
+ animatedStyle,
596
+ theme.containers.nowIndicator
574
597
  ] });
575
598
  };
576
599
  const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color }) => {
@@ -585,8 +608,8 @@ const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color
585
608
  return /* @__PURE__ */ jsx(Animated.View, {
586
609
  testID: "business-hours-shade",
587
610
  style: [
588
- styles.shadeBand,
589
- styles.nonInteractive,
611
+ styles$1.shadeBand,
612
+ styles$1.nonInteractive,
590
613
  {
591
614
  left,
592
615
  width,
@@ -650,7 +673,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
650
673
  const { locationX, locationY } = event.nativeEvent;
651
674
  const day = days[days.length === 1 ? 0 : Math.floor(locationX / dayWidth)];
652
675
  if (!day) return null;
653
- const minutes = Math.round((minHour + locationY / heightSource.value) * MINUTES_PER_HOUR);
676
+ const minutes = Math.round((minHour + locationY / heightSource.value) * MINUTES_PER_HOUR$1);
654
677
  const pressed = new Date(day);
655
678
  pressed.setHours(0, 0, 0, 0);
656
679
  pressed.setMinutes(minutes);
@@ -667,7 +690,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
667
690
  const hoursRange = useMemo(() => Array.from({ length: maxHour - minHour }, (_, index) => minHour + index), [minHour, maxHour]);
668
691
  const now = useNow(showNowIndicator && isActive);
669
692
  const nowDayIndex = days.findIndex((day) => getIsToday$1(day));
670
- const nowHours = (getHours(now) * MINUTES_PER_HOUR + getMinutes(now)) / MINUTES_PER_HOUR;
693
+ const nowHours = (getHours(now) * MINUTES_PER_HOUR$1 + getMinutes(now)) / MINUTES_PER_HOUR$1;
671
694
  const nowInWindow = nowHours >= minHour && nowHours <= maxHour;
672
695
  const fullHeightStyle = useAnimatedStyle(() => ({ height: (maxHour - minHour) * heightSource.value }), [
673
696
  minHour,
@@ -715,7 +738,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
715
738
  const tapCell = useCallback((x, y) => {
716
739
  const day = days[days.length === 1 ? 0 : Math.floor(x / dayWidth)];
717
740
  if (!day) return;
718
- const minutes = Math.round((minHour + y / heightSource.value) * MINUTES_PER_HOUR);
741
+ const minutes = Math.round((minHour + y / heightSource.value) * MINUTES_PER_HOUR$1);
719
742
  const pressed = new Date(day);
720
743
  pressed.setHours(0, 0, 0, 0);
721
744
  pressed.setMinutes(minutes);
@@ -740,7 +763,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
740
763
  createCancelled.value = 0;
741
764
  }).onUpdate((event) => {
742
765
  if (createCancelled.value) return;
743
- const stepPx = snapMinutes / MINUTES_PER_HOUR * heightSource.value;
766
+ const stepPx = snapMinutes / MINUTES_PER_HOUR$1 * heightSource.value;
744
767
  const snap = (y) => stepPx > 0 ? Math.round(y / stepPx) * stepPx : y;
745
768
  const startSnap = snap(createStartY.value);
746
769
  const endSnap = snap(createStartY.value + event.translationY);
@@ -809,7 +832,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
809
832
  opacity: createActive.value
810
833
  }));
811
834
  const cellLayer = onPressCell || onLongPressCell || createEnabled ? /* @__PURE__ */ jsx(Pressable, {
812
- style: [styles.cellPressLayer, { left: hourColumnWidth }],
835
+ style: [styles$1.cellPressLayer, { left: hourColumnWidth }],
813
836
  onPress: onPressCell ? handleBackgroundPress : void 0,
814
837
  onLongPress: !createEnabled && onLongPressCell ? handleBackgroundLongPress : void 0,
815
838
  tabIndex: -1,
@@ -817,7 +840,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
817
840
  accessibilityElementsHidden: true
818
841
  }) : null;
819
842
  return /* @__PURE__ */ jsxs(View, {
820
- style: styles.container,
843
+ style: styles$1.container,
821
844
  children: [showAllDayEventCell ? /* @__PURE__ */ jsx(AllDayLane, {
822
845
  days,
823
846
  events,
@@ -842,15 +865,15 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
842
865
  y: initialScrollY
843
866
  },
844
867
  children: /* @__PURE__ */ jsxs(Animated.View, {
845
- style: [styles.content, fullHeightStyle],
868
+ style: [styles$1.content, fullHeightStyle],
846
869
  children: [
847
870
  cellLayer && backgroundGesture ? /* @__PURE__ */ jsx(GestureDetector, {
848
871
  gesture: backgroundGesture,
849
872
  children: cellLayer
850
873
  }) : cellLayer,
851
874
  days.map((day, dayIndex) => isWeekend$1(day) ? /* @__PURE__ */ jsx(Animated.View, { style: [
852
- styles.weekendColumn,
853
- styles.nonInteractive,
875
+ styles$1.weekendColumn,
876
+ styles$1.nonInteractive,
854
877
  { backgroundColor: theme.colors.weekendBackground },
855
878
  {
856
879
  left: dayLeft(dayIndex),
@@ -861,8 +884,8 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
861
884
  calendarCellStyle ? days.map((day, dayIndex) => {
862
885
  const cellStyle = calendarCellStyle(day);
863
886
  return cellStyle ? /* @__PURE__ */ jsx(Animated.View, { style: [
864
- styles.weekendColumn,
865
- styles.nonInteractive,
887
+ styles$1.weekendColumn,
888
+ styles$1.nonInteractive,
866
889
  {
867
890
  left: dayLeft(dayIndex),
868
891
  width: dayWidth
@@ -881,8 +904,8 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
881
904
  color: theme.colors.outsideHoursBackground
882
905
  }, `closed-${day.toISOString()}-${bandIndex}`))) : null,
883
906
  days.map((day, dayIndex) => /* @__PURE__ */ jsx(Animated.View, { style: [
884
- styles.daySeparator,
885
- styles.nonInteractive,
907
+ styles$1.daySeparator,
908
+ styles$1.nonInteractive,
886
909
  { backgroundColor: theme.colors.gridLine },
887
910
  { left: dayLeft(dayIndex) },
888
911
  fullHeightStyle
@@ -933,7 +956,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
933
956
  color: theme.colors.nowIndicator
934
957
  }) : null,
935
958
  createEnabled ? /* @__PURE__ */ jsx(Animated.View, { style: [
936
- styles.createGhost,
959
+ styles$1.createGhost,
937
960
  { pointerEvents: "none" },
938
961
  {
939
962
  backgroundColor: theme.colors.eventBackground,
@@ -948,10 +971,15 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
948
971
  });
949
972
  }
950
973
  const TimetablePage = memo(TimetablePageInner);
951
- function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellHeight, hourHeight = 48, weekStartsOn, renderEvent, keyExtractor, scrollOffsetMinutes = 0, hourColumnWidth: hourColumnWidthProp = DEFAULT_HOUR_COLUMN_WIDTH, hideHours = false, timeslots = 1, showAllDayEventCell = true, calendarCellStyle, businessHours, showWeekNumber = false, headerComponent, minHour = 0, maxHour = HOURS_PER_DAY, ampm = false, isRTL = false, minHourHeight = DEFAULT_MIN_HOUR_HEIGHT, maxHourHeight = DEFAULT_MAX_HOUR_HEIGHT, showNowIndicator = true, locale, freeSwipe = false, swipeEnabled = true, showVerticalScrollIndicator = true, verticalScrollEnabled = true, weekNumberPrefix = "W", hourComponent, activeDate, resetPageOnPressCell = false, dragStepMinutes = DEFAULT_DRAG_STEP_MINUTES, showDragHandle = true, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, onPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, onChangeDate, renderHeader }) {
974
+ 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 }) {
952
975
  const clampedMinHour = Math.max(0, Math.min(minHour, HOURS_PER_DAY - 1));
953
976
  const clampedMaxHour = Math.max(clampedMinHour + 1, Math.min(maxHour, HOURS_PER_DAY));
954
977
  const hourColumnWidth = hideHours ? 0 : hourColumnWidthProp;
978
+ const labeledRenderEvent = useMemo(() => withEventAccessibilityLabel(renderEvent, eventAccessibilityLabel, ampm), [
979
+ renderEvent,
980
+ eventAccessibilityLabel,
981
+ ampm
982
+ ]);
955
983
  const { width, height } = useWindowDimensions();
956
984
  const listRef = useRef(null);
957
985
  const containerRef = useRef(null);
@@ -961,7 +989,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
961
989
  const [measured, setMeasured] = useState(false);
962
990
  const weekAnchored = mode === "week" || mode === "custom" && weekEndsOn != null;
963
991
  const step = weekAnchored ? 7 : viewDayCount(mode, numberOfDays);
964
- const seedDefaultY = Math.max(0, scrollOffsetMinutes / MINUTES_PER_HOUR - clampedMinHour) * hourHeight;
992
+ const seedDefaultY = Math.max(0, scrollOffsetMinutes / MINUTES_PER_HOUR$1 - clampedMinHour) * hourHeight;
965
993
  const scrollY = useSharedValue(seedDefaultY);
966
994
  const offsetSeedRef = useRef(null);
967
995
  const captureOffsetSeed = useCallback((y) => {
@@ -1143,7 +1171,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1143
1171
  minHourHeight,
1144
1172
  maxHourHeight,
1145
1173
  showNowIndicator,
1146
- renderEvent,
1174
+ renderEvent: labeledRenderEvent,
1147
1175
  keyExtractor,
1148
1176
  snapMinutes: Math.max(1, dragStepMinutes),
1149
1177
  showDragHandle,
@@ -1185,7 +1213,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1185
1213
  minHourHeight,
1186
1214
  maxHourHeight,
1187
1215
  showNowIndicator,
1188
- renderEvent,
1216
+ labeledRenderEvent,
1189
1217
  keyExtractor,
1190
1218
  dragStepMinutes,
1191
1219
  showDragHandle,
@@ -1203,7 +1231,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1203
1231
  }), [events, activeIndex]);
1204
1232
  return /* @__PURE__ */ jsxs(View, {
1205
1233
  ref: containerRef,
1206
- style: styles.container,
1234
+ style: styles$1.container,
1207
1235
  children: [
1208
1236
  renderHeader ? renderHeader(headerDays) : /* @__PURE__ */ jsx(DefaultHeader, {
1209
1237
  days: headerDays,
@@ -1212,13 +1240,14 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1212
1240
  hourColumnWidth,
1213
1241
  showWeekNumber,
1214
1242
  weekNumberPrefix,
1243
+ weekdayFormat,
1215
1244
  locale,
1216
1245
  activeDate,
1217
1246
  onPressDateHeader
1218
1247
  }),
1219
1248
  headerComponent,
1220
1249
  /* @__PURE__ */ jsx(View, {
1221
- style: styles.pager,
1250
+ style: styles$1.pager,
1222
1251
  onLayout: (event) => {
1223
1252
  setPageHeight(event.nativeEvent.layout.height);
1224
1253
  setContainerWidth(event.nativeEvent.layout.width);
@@ -1226,7 +1255,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1226
1255
  },
1227
1256
  children: /* @__PURE__ */ jsx(LegendList, {
1228
1257
  ref: listRef,
1229
- style: isWeb ? [styles.pagerList, styles.webNoScroll] : styles.pagerList,
1258
+ style: isWeb ? [styles$1.pagerList, styles$1.webNoScroll] : styles$1.pagerList,
1230
1259
  data: pageDates,
1231
1260
  extraData: listExtraData,
1232
1261
  horizontal: true,
@@ -1268,13 +1297,13 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1268
1297
  * ```
1269
1298
  */
1270
1299
  const TimeGrid = memo(TimeGridInner);
1271
- const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, weekNumberPrefix = "W", locale, activeDate, onPressDateHeader }) => {
1300
+ const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, weekNumberPrefix = "W", weekdayFormat, locale, activeDate, onPressDateHeader }) => {
1272
1301
  const theme = useCalendarTheme();
1273
1302
  const dayWidth = (width - hourColumnWidth) / days.length;
1274
1303
  return /* @__PURE__ */ jsxs(View, {
1275
- style: [styles.headerRow, { borderBottomColor: theme.colors.gridLine }],
1304
+ style: [styles$1.headerRow, { borderBottomColor: theme.colors.gridLine }],
1276
1305
  children: [/* @__PURE__ */ jsx(View, {
1277
- style: [styles.weekNumberGutter, { width: hourColumnWidth }],
1306
+ style: [styles$1.weekNumberGutter, { width: hourColumnWidth }],
1278
1307
  children: showWeekNumber && hourColumnWidth > 0 && days[0] ? /* @__PURE__ */ jsx(Text, {
1279
1308
  style: [theme.text.hourLabel, { color: theme.colors.textMuted }],
1280
1309
  allowFontScaling: false,
@@ -1284,29 +1313,40 @@ const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, wee
1284
1313
  day,
1285
1314
  mode,
1286
1315
  width: dayWidth,
1316
+ weekdayFormat,
1287
1317
  locale,
1288
1318
  activeDate,
1289
1319
  onPressDateHeader
1290
1320
  }, day.toISOString()))]
1291
1321
  });
1292
1322
  };
1293
- const DayHeader = ({ day, width, locale, activeDate, onPressDateHeader }) => {
1323
+ const DayHeader = ({ day, width, weekdayFormat = "short", locale, activeDate, onPressDateHeader }) => {
1294
1324
  const theme = useCalendarTheme();
1295
1325
  const isToday = getIsToday$1(day);
1296
1326
  const isHighlighted = activeDate ? isSameCalendarDay$1(day, activeDate) : isToday;
1297
1327
  return /* @__PURE__ */ jsxs(Pressable, {
1298
- style: [styles.dayHeader, { width }],
1328
+ style: [
1329
+ styles$1.dayHeader,
1330
+ { width },
1331
+ theme.containers.columnHeader
1332
+ ],
1299
1333
  onPress: onPressDateHeader ? () => onPressDateHeader(day) : void 0,
1300
1334
  disabled: !onPressDateHeader,
1301
1335
  accessibilityRole: onPressDateHeader ? "button" : void 0,
1336
+ accessibilityLabel: onPressDateHeader ? format(day, "EEEE d MMMM", { locale }) : void 0,
1302
1337
  children: [/* @__PURE__ */ jsx(Text, {
1303
- style: [styles.dayHeaderWeekday, { color: theme.colors.textMuted }],
1338
+ style: [{ color: theme.colors.textMuted }, theme.text.columnHeaderWeekday],
1304
1339
  allowFontScaling: false,
1305
- children: format(day, "EEE", { locale })
1340
+ children: format(day, weekdayFormatToken$1(weekdayFormat), { locale })
1306
1341
  }), /* @__PURE__ */ jsx(View, {
1307
- style: [styles.dayHeaderBadge, isHighlighted && { backgroundColor: theme.colors.todayBackground }],
1342
+ testID: "column-header-badge",
1343
+ style: [
1344
+ styles$1.dayHeaderBadge,
1345
+ theme.containers.columnHeaderBadge,
1346
+ isHighlighted && { backgroundColor: theme.colors.todayBackground }
1347
+ ],
1308
1348
  children: /* @__PURE__ */ jsx(Text, {
1309
- style: [styles.dayHeaderNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }],
1349
+ style: [theme.text.dayNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }],
1310
1350
  allowFontScaling: false,
1311
1351
  ...isToday && { accessibilityLabel: `Today, ${day.getDate()}` },
1312
1352
  children: day.getDate()
@@ -1314,7 +1354,7 @@ const DayHeader = ({ day, width, locale, activeDate, onPressDateHeader }) => {
1314
1354
  })]
1315
1355
  });
1316
1356
  };
1317
- const styles = StyleSheet.create({
1357
+ const styles$1 = StyleSheet.create({
1318
1358
  pager: { flex: 1 },
1319
1359
  pagerList: { flex: 1 },
1320
1360
  container: { flex: 1 },
@@ -1332,10 +1372,6 @@ const styles = StyleSheet.create({
1332
1372
  gap: 2,
1333
1373
  paddingVertical: 6
1334
1374
  },
1335
- dayHeaderWeekday: {
1336
- fontSize: 11,
1337
- fontWeight: "600"
1338
- },
1339
1375
  dayHeaderBadge: {
1340
1376
  width: 28,
1341
1377
  height: 28,
@@ -1343,10 +1379,6 @@ const styles = StyleSheet.create({
1343
1379
  justifyContent: "center",
1344
1380
  alignItems: "center"
1345
1381
  },
1346
- dayHeaderNumber: {
1347
- fontSize: 15,
1348
- fontWeight: "600"
1349
- },
1350
1382
  content: {
1351
1383
  width: "100%",
1352
1384
  position: "relative"
@@ -1456,7 +1488,7 @@ function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1456
1488
  * }
1457
1489
  * ```
1458
1490
  */
1459
- function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn = 0, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventCellStyle, calendarCellStyle, businessHours, keyExtractor = defaultKeyExtractor, theme, cellHeight: cellHeightProp, hourHeight = 48, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent }) {
1491
+ 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 }) {
1460
1492
  const mergedTheme = useMemo(() => mergeTheme(theme), [theme]);
1461
1493
  const internalCellHeight = useSharedValue(hourHeight);
1462
1494
  const cellHeight = cellHeightProp ?? internalCellHeight;
@@ -1478,7 +1510,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1478
1510
  weekEndsOn
1479
1511
  ]);
1480
1512
  const resolvedRenderEvent = useMemo(() => {
1481
- if (eventCellStyle == null && ampm == null && showTime == null && ellipsizeTitle == null && allDayLabel == null) return renderEvent;
1513
+ if (eventCellStyle == null && ampm == null && showTime == null && ellipsizeTitle == null && allDayLabel == null && eventAccessibilityLabel == null) return renderEvent;
1482
1514
  const Base = renderEvent;
1483
1515
  return function StyledEvent(props) {
1484
1516
  const cellStyle = typeof eventCellStyle === "function" ? eventCellStyle(props.event) : eventCellStyle;
@@ -1488,7 +1520,12 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1488
1520
  ampm,
1489
1521
  showTime,
1490
1522
  ellipsizeTitle,
1491
- allDayLabel
1523
+ allDayLabel,
1524
+ accessibilityLabel: eventAccessibilityLabel ? eventAccessibilityLabel(props.event, {
1525
+ mode: props.mode,
1526
+ isAllDay: props.isAllDay ?? false,
1527
+ ampm: ampm ?? false
1528
+ }) : props.accessibilityLabel
1492
1529
  });
1493
1530
  };
1494
1531
  }, [
@@ -1497,7 +1534,8 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1497
1534
  ampm,
1498
1535
  showTime,
1499
1536
  ellipsizeTitle,
1500
- allDayLabel
1537
+ allDayLabel,
1538
+ eventAccessibilityLabel
1501
1539
  ]);
1502
1540
  return /* @__PURE__ */ jsx(CalendarThemeProvider, {
1503
1541
  value: mergedTheme,
@@ -1506,6 +1544,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1506
1544
  events,
1507
1545
  maxVisibleEventCount,
1508
1546
  weekStartsOn,
1547
+ weekdayFormat,
1509
1548
  locale,
1510
1549
  sortedMonthView,
1511
1550
  moreLabel,
@@ -1546,6 +1585,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1546
1585
  cellHeight,
1547
1586
  hourHeight,
1548
1587
  weekStartsOn,
1588
+ weekdayFormat,
1549
1589
  renderEvent: resolvedRenderEvent,
1550
1590
  keyExtractor,
1551
1591
  scrollOffsetMinutes,
@@ -1589,4 +1629,324 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1589
1629
  });
1590
1630
  }
1591
1631
  //#endregion
1592
- export { Agenda, Calendar, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, DefaultEvent, DefaultMonthEvent, MonthList, MonthPager, MonthView, TimeGrid, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid };
1632
+ //#region src/components/ResourceTimeline.tsx
1633
+ const MOVE_ACTIVATE_MS = 250;
1634
+ const MINUTES_PER_HOUR = 60;
1635
+ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
1636
+ function DefaultBar({ event, width }) {
1637
+ const theme = useCalendarTheme();
1638
+ const time = eventTimeLabel({
1639
+ mode: "day",
1640
+ isAllDay: false,
1641
+ start: event.start,
1642
+ end: event.end,
1643
+ ampm: false,
1644
+ showTime: true
1645
+ });
1646
+ return /* @__PURE__ */ jsxs(View, {
1647
+ style: [
1648
+ styles.bar,
1649
+ { backgroundColor: theme.colors.eventBackground },
1650
+ theme.containers.timeGridEvent
1651
+ ],
1652
+ children: [/* @__PURE__ */ jsx(Text, {
1653
+ numberOfLines: 1,
1654
+ style: [theme.text.eventTitle, { color: theme.colors.eventText }],
1655
+ allowFontScaling: false,
1656
+ children: event.title
1657
+ }), time && width > 56 ? /* @__PURE__ */ jsx(Text, {
1658
+ numberOfLines: 1,
1659
+ style: [styles.barTime, { color: theme.colors.eventText }],
1660
+ allowFontScaling: false,
1661
+ children: time
1662
+ }) : null]
1663
+ });
1664
+ }
1665
+ function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Renderer, onPress, onDragEvent, theme }) {
1666
+ const moveX = useSharedValue(0);
1667
+ const resizeW = useSharedValue(0);
1668
+ const latest = useRef({
1669
+ event: pe.event,
1670
+ onDragEvent
1671
+ });
1672
+ latest.current = {
1673
+ event: pe.event,
1674
+ onDragEvent
1675
+ };
1676
+ const draggable = !pe.event.disabled;
1677
+ useEffect(() => {
1678
+ moveX.value = 0;
1679
+ resizeW.value = 0;
1680
+ }, [
1681
+ pe.startHours,
1682
+ pe.durationHours,
1683
+ moveX,
1684
+ resizeW
1685
+ ]);
1686
+ const snapBack = useCallback(() => {
1687
+ moveX.value = 0;
1688
+ resizeW.value = 0;
1689
+ }, [moveX, resizeW]);
1690
+ const commit = useCallback((deltaStartMin, deltaEndMin) => {
1691
+ const { event, onDragEvent: handler } = latest.current;
1692
+ const next = resolveDraggedBounds(event.start, event.end, deltaStartMin, deltaEndMin, snapMinutes);
1693
+ if (!next) {
1694
+ snapBack();
1695
+ return;
1696
+ }
1697
+ if (handler(event, next.start, next.end) === false) snapBack();
1698
+ }, [snapMinutes, snapBack]);
1699
+ const barStyle = useAnimatedStyle(() => ({
1700
+ transform: [{ translateX: moveX.value }],
1701
+ width: Math.max(width + resizeW.value, 2)
1702
+ }), [width]);
1703
+ const moveGesture = useMemo(() => Gesture.Pan().enabled(draggable).activateAfterLongPress(MOVE_ACTIVATE_MS).onUpdate((e) => {
1704
+ moveX.value = e.translationX;
1705
+ }).onEnd((e) => {
1706
+ const delta = snapDeltaMinutes(e.translationX, hourWidth, snapMinutes);
1707
+ if (delta === 0) {
1708
+ moveX.value = 0;
1709
+ return;
1710
+ }
1711
+ moveX.value = delta / MINUTES_PER_HOUR * hourWidth;
1712
+ runOnJS(commit)(delta, delta);
1713
+ }), [
1714
+ draggable,
1715
+ hourWidth,
1716
+ snapMinutes,
1717
+ moveX,
1718
+ commit
1719
+ ]);
1720
+ const resizeGesture = useMemo(() => Gesture.Pan().enabled(draggable).onUpdate((e) => {
1721
+ resizeW.value = e.translationX;
1722
+ }).onEnd((e) => {
1723
+ const delta = snapDeltaMinutes(e.translationX, hourWidth, snapMinutes);
1724
+ if (delta === 0) {
1725
+ resizeW.value = 0;
1726
+ return;
1727
+ }
1728
+ resizeW.value = delta / MINUTES_PER_HOUR * hourWidth;
1729
+ runOnJS(commit)(0, delta);
1730
+ }), [
1731
+ draggable,
1732
+ hourWidth,
1733
+ snapMinutes,
1734
+ resizeW,
1735
+ commit
1736
+ ]);
1737
+ return /* @__PURE__ */ jsxs(Animated.View, {
1738
+ style: [{
1739
+ position: "absolute",
1740
+ left,
1741
+ top: pe.column * laneHeight,
1742
+ height: laneHeight,
1743
+ padding: 1
1744
+ }, barStyle],
1745
+ children: [/* @__PURE__ */ jsx(GestureDetector, {
1746
+ gesture: moveGesture,
1747
+ children: /* @__PURE__ */ jsx(Pressable, {
1748
+ onPress,
1749
+ accessibilityRole: "button",
1750
+ accessibilityLabel: pe.event.title,
1751
+ style: styles.fill,
1752
+ children: /* @__PURE__ */ jsx(Renderer, {
1753
+ event: pe.event,
1754
+ width,
1755
+ onPress
1756
+ })
1757
+ })
1758
+ }), /* @__PURE__ */ jsx(GestureDetector, {
1759
+ gesture: resizeGesture,
1760
+ children: /* @__PURE__ */ jsx(View, {
1761
+ style: [styles.resizeGrip, { backgroundColor: theme.colors.eventText }],
1762
+ accessibilityRole: "adjustable",
1763
+ accessibilityLabel: `Resize ${pe.event.title}`
1764
+ })
1765
+ })]
1766
+ });
1767
+ }
1768
+ /**
1769
+ * A horizontal resource timeline: rows are resources (rooms, people, machines)
1770
+ * and the x-axis is one day's hours. Events sit in their resource's row, and
1771
+ * overlapping events in the same row stack into sub-lanes (via the shared
1772
+ * `layoutDayEvents`). The grid scrolls horizontally when the axis is wider than
1773
+ * the screen. Pass `onDragEvent` to enable long-press drag-to-move and edge
1774
+ * resize along the time axis. Read the theme from context — wrap in
1775
+ * `CalendarThemeProvider` (or render inside `<Calendar>`) to restyle.
1776
+ *
1777
+ * @example
1778
+ * ```tsx
1779
+ * <ResourceTimeline
1780
+ * date={new Date()}
1781
+ * resources={[{ id: "a", title: "Room A" }, { id: "b", title: "Room B" }]}
1782
+ * events={events} // each event carries a `resourceId`
1783
+ * />
1784
+ * ```
1785
+ */
1786
+ 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 }) {
1787
+ const theme = useCalendarTheme();
1788
+ const Renderer = renderEvent ?? DefaultBar;
1789
+ const hours = useMemo(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
1790
+ const trackWidth = (endHour - startHour) * hourWidth;
1791
+ const byResource = useMemo(() => {
1792
+ const map = /* @__PURE__ */ new Map();
1793
+ for (const resource of resources) {
1794
+ const own = events.filter((event) => resourceId(event) === resource.id);
1795
+ map.set(resource.id, layoutDayEvents$1(own, date));
1796
+ }
1797
+ return map;
1798
+ }, [
1799
+ resources,
1800
+ events,
1801
+ resourceId,
1802
+ date
1803
+ ]);
1804
+ return /* @__PURE__ */ jsx(ScrollView, {
1805
+ horizontal: true,
1806
+ showsHorizontalScrollIndicator: true,
1807
+ style: styles.root,
1808
+ children: /* @__PURE__ */ jsxs(View, {
1809
+ style: { width: labelWidth + trackWidth },
1810
+ children: [/* @__PURE__ */ jsxs(View, {
1811
+ style: [styles.header, { borderBottomColor: theme.colors.gridLine }],
1812
+ children: [/* @__PURE__ */ jsx(View, { style: { width: labelWidth } }), /* @__PURE__ */ jsx(View, {
1813
+ style: {
1814
+ width: trackWidth,
1815
+ height: 24
1816
+ },
1817
+ children: hours.map((h) => /* @__PURE__ */ jsx(Text, {
1818
+ allowFontScaling: false,
1819
+ style: [styles.hourTick, {
1820
+ left: (h - startHour) * hourWidth,
1821
+ color: theme.colors.textMuted
1822
+ }],
1823
+ children: formatHour(h, { ampm })
1824
+ }, h))
1825
+ })]
1826
+ }), resources.map((resource) => {
1827
+ const positioned = byResource.get(resource.id) ?? [];
1828
+ return /* @__PURE__ */ jsxs(View, {
1829
+ style: [
1830
+ styles.row,
1831
+ {
1832
+ height: rowHeight,
1833
+ borderBottomColor: theme.colors.gridLine
1834
+ },
1835
+ theme.containers.resourceRow
1836
+ ],
1837
+ children: [/* @__PURE__ */ jsx(View, {
1838
+ style: [
1839
+ styles.label,
1840
+ {
1841
+ width: labelWidth,
1842
+ borderRightColor: theme.colors.gridLine
1843
+ },
1844
+ theme.containers.resourceLabel
1845
+ ],
1846
+ children: /* @__PURE__ */ jsx(Text, {
1847
+ numberOfLines: 1,
1848
+ style: { color: theme.colors.text },
1849
+ allowFontScaling: false,
1850
+ children: resource.title ?? resource.id
1851
+ })
1852
+ }), /* @__PURE__ */ jsxs(View, {
1853
+ style: { width: trackWidth },
1854
+ children: [hours.slice(1).map((h) => /* @__PURE__ */ jsx(View, {
1855
+ pointerEvents: "none",
1856
+ style: [styles.gridLine, {
1857
+ left: (h - startHour) * hourWidth,
1858
+ backgroundColor: theme.colors.gridLine
1859
+ }]
1860
+ }, h)), positioned.map((pe, idx) => {
1861
+ const left = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourWidth;
1862
+ const right = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourWidth;
1863
+ const width = Math.max(right - left, 2);
1864
+ const laneHeight = rowHeight / pe.columns;
1865
+ const onPress = () => onPressEvent?.(pe.event);
1866
+ if (onDragEvent) return /* @__PURE__ */ jsx(ResourceBar, {
1867
+ pe,
1868
+ left,
1869
+ width,
1870
+ laneHeight,
1871
+ hourWidth,
1872
+ snapMinutes: dragStepMinutes,
1873
+ Renderer,
1874
+ onPress,
1875
+ onDragEvent,
1876
+ theme
1877
+ }, idx);
1878
+ return /* @__PURE__ */ jsx(Pressable, {
1879
+ onPress,
1880
+ accessibilityRole: "button",
1881
+ accessibilityLabel: pe.event.title,
1882
+ style: {
1883
+ position: "absolute",
1884
+ left,
1885
+ width,
1886
+ top: pe.column * laneHeight,
1887
+ height: laneHeight,
1888
+ padding: 1
1889
+ },
1890
+ children: /* @__PURE__ */ jsx(Renderer, {
1891
+ event: pe.event,
1892
+ width,
1893
+ onPress
1894
+ })
1895
+ }, idx);
1896
+ })]
1897
+ })]
1898
+ }, resource.id);
1899
+ })]
1900
+ })
1901
+ });
1902
+ }
1903
+ const styles = StyleSheet.create({
1904
+ root: { flexGrow: 0 },
1905
+ header: {
1906
+ flexDirection: "row",
1907
+ borderBottomWidth: StyleSheet.hairlineWidth
1908
+ },
1909
+ hourTick: {
1910
+ position: "absolute",
1911
+ top: 4,
1912
+ fontSize: 10
1913
+ },
1914
+ row: {
1915
+ flexDirection: "row",
1916
+ borderBottomWidth: StyleSheet.hairlineWidth
1917
+ },
1918
+ label: {
1919
+ justifyContent: "center",
1920
+ paddingHorizontal: 10,
1921
+ borderRightWidth: StyleSheet.hairlineWidth
1922
+ },
1923
+ gridLine: {
1924
+ position: "absolute",
1925
+ top: 0,
1926
+ bottom: 0,
1927
+ width: StyleSheet.hairlineWidth
1928
+ },
1929
+ bar: {
1930
+ flex: 1,
1931
+ borderRadius: 6,
1932
+ paddingHorizontal: 6,
1933
+ paddingVertical: 2,
1934
+ overflow: "hidden"
1935
+ },
1936
+ barTime: {
1937
+ fontSize: 11,
1938
+ opacity: .75
1939
+ },
1940
+ fill: { flex: 1 },
1941
+ resizeGrip: {
1942
+ position: "absolute",
1943
+ right: 1,
1944
+ top: "30%",
1945
+ bottom: "30%",
1946
+ width: 4,
1947
+ borderRadius: 2,
1948
+ opacity: .5
1949
+ }
1950
+ });
1951
+ //#endregion
1952
+ export { Agenda, Calendar, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, DefaultEvent, DefaultMonthEvent, MonthList, MonthPager, MonthView, ResourceTimeline, TimeGrid, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };