@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.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-ege6HsEP.js");
24
+ const require_MonthList = require("./MonthList-CFXm7BK_.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");
@@ -67,14 +67,14 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
67
67
  if (item.kind === "header") {
68
68
  const isHighlighted = activeDate ? (0, date_fns.isSameDay)(item.date, activeDate) : (0, _super_calendar_core.getIsToday)(item.date);
69
69
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
70
- style: [styles$3.header, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }],
70
+ style: [styles$4.header, { color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted }],
71
71
  onPress: onPressDay ? () => onPressDay(item.date) : void 0,
72
72
  accessibilityRole: onPressDay ? "button" : "header",
73
73
  children: (0, date_fns.format)(item.date, "EEEE, d LLLL", { locale })
74
74
  });
75
75
  }
76
76
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
77
- style: styles$3.eventRow,
77
+ style: [styles$4.eventRow, theme.containers.agendaRow],
78
78
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
79
79
  event: item.event,
80
80
  mode: "schedule",
@@ -93,11 +93,11 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
93
93
  RenderEventComponent
94
94
  ]);
95
95
  if (rows.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
96
- style: [styles$3.empty, { color: theme.colors.textMuted }],
96
+ style: [styles$4.empty, { color: theme.colors.textMuted }],
97
97
  children: "No events"
98
98
  });
99
99
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
100
- style: styles$3.list,
100
+ style: [styles$4.list, theme.containers.agendaList],
101
101
  data: rows,
102
102
  keyExtractor: keyExtractorRow,
103
103
  renderItem,
@@ -105,7 +105,7 @@ function Agenda({ events, locale, renderEvent, keyExtractor, onPressEvent, onLon
105
105
  recycleItems: false
106
106
  });
107
107
  }
108
- const styles$3 = react_native.StyleSheet.create({
108
+ const styles$4 = react_native.StyleSheet.create({
109
109
  list: { flex: 1 },
110
110
  header: {
111
111
  fontSize: 13,
@@ -138,7 +138,7 @@ const numericStyle = (value, fallback) => typeof value === "number" ? value : fa
138
138
  * only shows once a full line is free beneath the title. Pass your own
139
139
  * `renderEvent` to `<Calendar>` to replace it entirely.
140
140
  */
141
- function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, cellStyle, onPress, onLongPress }) {
141
+ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime = true, ellipsizeTitle = false, allDayLabel, accessibilityLabel: accessibilityLabelProp, cellStyle, onPress, onLongPress }) {
142
142
  const theme = require_MonthList.useCalendarTheme();
143
143
  const isAllDayEvent = isAllDay ?? false;
144
144
  const timeLabel = (0, _super_calendar_core.eventTimeLabel)({
@@ -152,7 +152,7 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
152
152
  });
153
153
  const ellipsizeMode = (0, _super_calendar_core.titleEllipsizeMode)(ellipsizeTitle);
154
154
  const titleLineHeight = numericStyle(theme.text.eventTitle.lineHeight, FALLBACK_TITLE_LINE_HEIGHT);
155
- const accessibilityLabel = (0, _super_calendar_core.eventAccessibilityLabel)({
155
+ const accessibilityLabel = accessibilityLabelProp ?? (0, _super_calendar_core.eventAccessibilityLabel)({
156
156
  title: event.title,
157
157
  isAllDay: isAllDayEvent,
158
158
  start: event.start,
@@ -182,12 +182,16 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
182
182
  const timeStyle = (0, react_native_reanimated.useAnimatedStyle)(() => {
183
183
  return { display: layout.value.showTime ? "flex" : "none" };
184
184
  }, [layout]);
185
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.TouchableOpacity, {
185
+ const contentStyle = (0, react_native_reanimated.useAnimatedStyle)(() => {
186
+ const { titleMaxLines, showTime } = layout.value;
187
+ return { justifyContent: titleMaxLines === 1 && !showTime ? "center" : "flex-start" };
188
+ }, [layout]);
189
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
186
190
  style: [
187
- styles$2.box,
188
- isSchedule && styles$2.scheduleBox,
191
+ styles$3.box,
192
+ isSchedule && styles$3.scheduleBox,
189
193
  { backgroundColor: theme.colors.eventBackground },
190
- event.disabled && styles$2.disabled,
194
+ event.disabled && styles$3.disabled,
191
195
  cellStyle
192
196
  ],
193
197
  onPress,
@@ -196,46 +200,50 @@ function DefaultEvent({ event, mode, boxHeight, isAllDay, ampm = false, showTime
196
200
  accessibilityRole: "button",
197
201
  accessibilityLabel,
198
202
  accessibilityState: { disabled: event.disabled ?? false },
199
- children: [event.title ? fixedTitleLines == null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
200
- style: [styles$2.titleClip, titleClipStyle],
201
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
203
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
204
+ testID: "event-chip-content",
205
+ style: [styles$3.content, contentStyle],
206
+ children: [event.title ? fixedTitleLines == null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
207
+ style: [styles$3.titleClip, titleClipStyle],
208
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
209
+ style: [
210
+ theme.text.eventTitle,
211
+ isSchedule && styles$3.scheduleTitle,
212
+ { color: theme.colors.eventText }
213
+ ],
214
+ ellipsizeMode,
215
+ allowFontScaling: false,
216
+ children: event.title
217
+ })
218
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
202
219
  style: [
203
220
  theme.text.eventTitle,
204
- isSchedule && styles$2.scheduleTitle,
221
+ styles$3.title,
222
+ isSchedule && styles$3.scheduleTitle,
205
223
  { color: theme.colors.eventText }
206
224
  ],
225
+ numberOfLines: fixedTitleLines,
207
226
  ellipsizeMode,
208
227
  allowFontScaling: false,
209
228
  children: event.title
210
- })
211
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
212
- style: [
213
- theme.text.eventTitle,
214
- styles$2.title,
215
- isSchedule && styles$2.scheduleTitle,
216
- { color: theme.colors.eventText }
217
- ],
218
- numberOfLines: fixedTitleLines,
219
- ellipsizeMode,
220
- allowFontScaling: false,
221
- children: event.title
222
- }) : null, timeLabel ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
223
- style: timeStyle,
224
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
225
- style: [
226
- styles$2.time,
227
- isSchedule && styles$2.scheduleTime,
228
- { color: theme.colors.eventText }
229
- ],
230
- numberOfLines: 2,
231
- ellipsizeMode,
232
- allowFontScaling: false,
233
- children: timeLabel
234
- })
235
- }) : null]
229
+ }) : null, timeLabel ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
230
+ style: timeStyle,
231
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
232
+ style: [
233
+ styles$3.time,
234
+ isSchedule && styles$3.scheduleTime,
235
+ { color: theme.colors.eventText }
236
+ ],
237
+ numberOfLines: 2,
238
+ ellipsizeMode,
239
+ allowFontScaling: false,
240
+ children: timeLabel
241
+ })
242
+ }) : null]
243
+ })
236
244
  });
237
245
  }
238
- const styles$2 = react_native.StyleSheet.create({
246
+ const styles$3 = react_native.StyleSheet.create({
239
247
  box: {
240
248
  flexGrow: 1,
241
249
  flexShrink: 1,
@@ -260,6 +268,10 @@ const styles$2 = react_native.StyleSheet.create({
260
268
  lineHeight: 18,
261
269
  opacity: .75
262
270
  },
271
+ content: {
272
+ flexGrow: 1,
273
+ flexShrink: 1
274
+ },
263
275
  titleClip: { overflow: "hidden" },
264
276
  title: { flexShrink: 1 },
265
277
  time: {
@@ -319,18 +331,26 @@ function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent
319
331
  });
320
332
  if (perDay.every((list) => list.length === 0)) return null;
321
333
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
322
- style: [styles$1.lane, { borderBottomColor: theme.colors.gridLine }],
334
+ style: [
335
+ styles$2.lane,
336
+ { borderBottomColor: theme.colors.gridLine },
337
+ theme.containers.allDayLane
338
+ ],
323
339
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
324
- style: [styles$1.gutter, { width: hourColumnWidth }],
340
+ style: [styles$2.gutter, { width: hourColumnWidth }],
325
341
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
326
- style: [styles$1.label, { color: theme.colors.textMuted }],
342
+ style: [styles$2.label, { color: theme.colors.textMuted }],
327
343
  allowFontScaling: false,
328
344
  children: "all-day"
329
345
  })
330
346
  }), days.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
331
- style: [styles$1.column, { width: dayWidth }],
347
+ style: [
348
+ styles$2.column,
349
+ { width: dayWidth },
350
+ theme.containers.allDayColumn
351
+ ],
332
352
  children: perDay[dayIndex].map((event, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
333
- style: styles$1.chip,
353
+ style: styles$2.chip,
334
354
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
335
355
  event,
336
356
  mode,
@@ -342,7 +362,7 @@ function AllDayLane({ days, events, mode, hourColumnWidth, dayWidth, renderEvent
342
362
  }, day.toISOString()))]
343
363
  });
344
364
  }
345
- const styles$1 = react_native.StyleSheet.create({
365
+ const styles$2 = react_native.StyleSheet.create({
346
366
  lane: {
347
367
  flexDirection: "row",
348
368
  borderBottomWidth: react_native.StyleSheet.hairlineWidth
@@ -363,9 +383,9 @@ const styles$1 = react_native.StyleSheet.create({
363
383
  //#endregion
364
384
  //#region src/components/TimeGrid.tsx
365
385
  const isWeb = react_native.Platform.OS === "web";
366
- const MINUTES_PER_HOUR = 60;
386
+ const MINUTES_PER_HOUR$1 = 60;
367
387
  const HOURS_PER_DAY = 24;
368
- const MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
388
+ const MINUTES_PER_DAY = MINUTES_PER_HOUR$1 * HOURS_PER_DAY;
369
389
  const PAGE_WINDOW = 180;
370
390
  const PAGE_VIEWABILITY = { itemVisiblePercentThreshold: 90 };
371
391
  /** Default height in pixels of one hour row on the time grid. */
@@ -376,7 +396,7 @@ const DEFAULT_HOUR_COLUMN_WIDTH = 56;
376
396
  const MIN_EVENT_HEIGHT = 32;
377
397
  const EVENT_GAP = 2;
378
398
  const DRAG_ACTIVATE_MS = 300;
379
- const MOVE_ACTIVATE_MS = 500;
399
+ const MOVE_ACTIVATE_MS$1 = 500;
380
400
  const DRAG_ACTIVATE_PX = 8;
381
401
  const RESIZE_HANDLE_HEIGHT = 14;
382
402
  const DEFAULT_DRAG_STEP_MINUTES = 15;
@@ -470,12 +490,12 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
470
490
  moveOffsetX.value = 0;
471
491
  return;
472
492
  }
473
- moveOffset.value = minuteDelta / MINUTES_PER_HOUR * cellHeight.value;
493
+ moveOffset.value = minuteDelta / MINUTES_PER_HOUR$1 * cellHeight.value;
474
494
  moveOffsetX.value = dayDelta * dayWidth;
475
495
  const totalDelta = minuteDelta + dayDelta * MINUTES_PER_DAY;
476
496
  (0, react_native_reanimated.runOnJS)(commitDrag)(totalDelta, totalDelta);
477
497
  });
478
- return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS);
498
+ return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS$1);
479
499
  }, [
480
500
  draggable,
481
501
  snapMinutes,
@@ -498,7 +518,7 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
498
518
  resizeDelta.value = 0;
499
519
  return;
500
520
  }
501
- resizeDelta.value = delta / MINUTES_PER_HOUR * cellHeight.value;
521
+ resizeDelta.value = delta / MINUTES_PER_HOUR$1 * cellHeight.value;
502
522
  (0, react_native_reanimated.runOnJS)(commitDrag)(0, delta);
503
523
  }), [
504
524
  resizable,
@@ -512,12 +532,13 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
512
532
  const handleLongPress = !draggable && onLongPress ? () => onLongPress(positioned.event) : void 0;
513
533
  const box = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
514
534
  style: [
515
- styles.eventBox,
535
+ styles$1.eventBox,
516
536
  {
517
537
  left,
518
538
  width
519
539
  },
520
- boxStyle
540
+ boxStyle,
541
+ theme.containers.timeGridEvent
521
542
  ],
522
543
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderEventComponent, {
523
544
  event: positioned.event,
@@ -530,8 +551,8 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
530
551
  }), resizable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
531
552
  gesture: resizeGesture,
532
553
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
533
- style: styles.resizeHandle,
534
- children: showDragHandle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles.resizeGrip, { backgroundColor: theme.colors.eventText }] }) : null
554
+ style: styles$1.resizeHandle,
555
+ children: showDragHandle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles$1.resizeGrip, { backgroundColor: theme.colors.eventText }] }) : null
535
556
  })
536
557
  }) : null]
537
558
  });
@@ -546,8 +567,8 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
546
567
  const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (hour - minHour) * cellHeight.value }), [hour, minHour]);
547
568
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
548
569
  style: [
549
- styles.hourRow,
550
- styles.nonInteractive,
570
+ styles$1.hourRow,
571
+ styles$1.nonInteractive,
551
572
  animatedStyle
552
573
  ],
553
574
  children: [hourComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
@@ -556,7 +577,7 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
556
577
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
557
578
  style: [
558
579
  theme.text.hourLabel,
559
- styles.hourLabel,
580
+ styles$1.hourLabel,
560
581
  {
561
582
  width: hourColumnWidth,
562
583
  color: theme.colors.textMuted
@@ -564,7 +585,7 @@ const HourRow = ({ hour, minHour, cellHeight, hourColumnWidth, label, ampm, hour
564
585
  ],
565
586
  allowFontScaling: false,
566
587
  children: label
567
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles.hourLine, { backgroundColor: theme.colors.gridLine }] })]
588
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [styles$1.hourLine, { backgroundColor: theme.colors.gridLine }] })]
568
589
  });
569
590
  };
570
591
  const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth }) => {
@@ -575,8 +596,8 @@ const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth })
575
596
  fraction
576
597
  ]);
577
598
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
578
- styles.timeslotLine,
579
- styles.nonInteractive,
599
+ styles$1.timeslotLine,
600
+ styles$1.nonInteractive,
580
601
  {
581
602
  left: hourColumnWidth,
582
603
  backgroundColor: theme.colors.gridLine
@@ -585,16 +606,18 @@ const TimeslotLine = ({ hour, minHour, fraction, cellHeight, hourColumnWidth })
585
606
  ] });
586
607
  };
587
608
  const NowIndicator = ({ cellHeight, nowHours, minHour, left, width, color }) => {
609
+ const theme = require_MonthList.useCalendarTheme();
588
610
  const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ top: (nowHours - minHour) * cellHeight.value }), [nowHours, minHour]);
589
611
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
590
- styles.nowIndicator,
591
- styles.nonInteractive,
612
+ styles$1.nowIndicator,
613
+ styles$1.nonInteractive,
592
614
  {
593
615
  left,
594
616
  width,
595
617
  backgroundColor: color
596
618
  },
597
- animatedStyle
619
+ animatedStyle,
620
+ theme.containers.nowIndicator
598
621
  ] });
599
622
  };
600
623
  const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color }) => {
@@ -609,8 +632,8 @@ const ShadeBand = ({ cellHeight, startHour, endHour, minHour, left, width, color
609
632
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
610
633
  testID: "business-hours-shade",
611
634
  style: [
612
- styles.shadeBand,
613
- styles.nonInteractive,
635
+ styles$1.shadeBand,
636
+ styles$1.nonInteractive,
614
637
  {
615
638
  left,
616
639
  width,
@@ -674,7 +697,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
674
697
  const { locationX, locationY } = event.nativeEvent;
675
698
  const day = days[days.length === 1 ? 0 : Math.floor(locationX / dayWidth)];
676
699
  if (!day) return null;
677
- const minutes = Math.round((minHour + locationY / heightSource.value) * MINUTES_PER_HOUR);
700
+ const minutes = Math.round((minHour + locationY / heightSource.value) * MINUTES_PER_HOUR$1);
678
701
  const pressed = new Date(day);
679
702
  pressed.setHours(0, 0, 0, 0);
680
703
  pressed.setMinutes(minutes);
@@ -691,7 +714,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
691
714
  const hoursRange = (0, react.useMemo)(() => Array.from({ length: maxHour - minHour }, (_, index) => minHour + index), [minHour, maxHour]);
692
715
  const now = useNow(showNowIndicator && isActive);
693
716
  const nowDayIndex = days.findIndex((day) => (0, _super_calendar_core.getIsToday)(day));
694
- const nowHours = ((0, date_fns.getHours)(now) * MINUTES_PER_HOUR + (0, date_fns.getMinutes)(now)) / MINUTES_PER_HOUR;
717
+ const nowHours = ((0, date_fns.getHours)(now) * MINUTES_PER_HOUR$1 + (0, date_fns.getMinutes)(now)) / MINUTES_PER_HOUR$1;
695
718
  const nowInWindow = nowHours >= minHour && nowHours <= maxHour;
696
719
  const fullHeightStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({ height: (maxHour - minHour) * heightSource.value }), [
697
720
  minHour,
@@ -739,7 +762,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
739
762
  const tapCell = (0, react.useCallback)((x, y) => {
740
763
  const day = days[days.length === 1 ? 0 : Math.floor(x / dayWidth)];
741
764
  if (!day) return;
742
- const minutes = Math.round((minHour + y / heightSource.value) * MINUTES_PER_HOUR);
765
+ const minutes = Math.round((minHour + y / heightSource.value) * MINUTES_PER_HOUR$1);
743
766
  const pressed = new Date(day);
744
767
  pressed.setHours(0, 0, 0, 0);
745
768
  pressed.setMinutes(minutes);
@@ -764,7 +787,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
764
787
  createCancelled.value = 0;
765
788
  }).onUpdate((event) => {
766
789
  if (createCancelled.value) return;
767
- const stepPx = snapMinutes / MINUTES_PER_HOUR * heightSource.value;
790
+ const stepPx = snapMinutes / MINUTES_PER_HOUR$1 * heightSource.value;
768
791
  const snap = (y) => stepPx > 0 ? Math.round(y / stepPx) * stepPx : y;
769
792
  const startSnap = snap(createStartY.value);
770
793
  const endSnap = snap(createStartY.value + event.translationY);
@@ -833,7 +856,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
833
856
  opacity: createActive.value
834
857
  }));
835
858
  const cellLayer = onPressCell || onLongPressCell || createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
836
- style: [styles.cellPressLayer, { left: hourColumnWidth }],
859
+ style: [styles$1.cellPressLayer, { left: hourColumnWidth }],
837
860
  onPress: onPressCell ? handleBackgroundPress : void 0,
838
861
  onLongPress: !createEnabled && onLongPressCell ? handleBackgroundLongPress : void 0,
839
862
  tabIndex: -1,
@@ -841,7 +864,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
841
864
  accessibilityElementsHidden: true
842
865
  }) : null;
843
866
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
844
- style: styles.container,
867
+ style: styles$1.container,
845
868
  children: [showAllDayEventCell ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AllDayLane, {
846
869
  days,
847
870
  events,
@@ -866,15 +889,15 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
866
889
  y: initialScrollY
867
890
  },
868
891
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_reanimated.default.View, {
869
- style: [styles.content, fullHeightStyle],
892
+ style: [styles$1.content, fullHeightStyle],
870
893
  children: [
871
894
  cellLayer && backgroundGesture ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
872
895
  gesture: backgroundGesture,
873
896
  children: cellLayer
874
897
  }) : cellLayer,
875
898
  days.map((day, dayIndex) => (0, _super_calendar_core.isWeekend)(day) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
876
- styles.weekendColumn,
877
- styles.nonInteractive,
899
+ styles$1.weekendColumn,
900
+ styles$1.nonInteractive,
878
901
  { backgroundColor: theme.colors.weekendBackground },
879
902
  {
880
903
  left: dayLeft(dayIndex),
@@ -885,8 +908,8 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
885
908
  calendarCellStyle ? days.map((day, dayIndex) => {
886
909
  const cellStyle = calendarCellStyle(day);
887
910
  return cellStyle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
888
- styles.weekendColumn,
889
- styles.nonInteractive,
911
+ styles$1.weekendColumn,
912
+ styles$1.nonInteractive,
890
913
  {
891
914
  left: dayLeft(dayIndex),
892
915
  width: dayWidth
@@ -905,8 +928,8 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
905
928
  color: theme.colors.outsideHoursBackground
906
929
  }, `closed-${day.toISOString()}-${bandIndex}`))) : null,
907
930
  days.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
908
- styles.daySeparator,
909
- styles.nonInteractive,
931
+ styles$1.daySeparator,
932
+ styles$1.nonInteractive,
910
933
  { backgroundColor: theme.colors.gridLine },
911
934
  { left: dayLeft(dayIndex) },
912
935
  fullHeightStyle
@@ -957,7 +980,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
957
980
  color: theme.colors.nowIndicator
958
981
  }) : null,
959
982
  createEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, { style: [
960
- styles.createGhost,
983
+ styles$1.createGhost,
961
984
  { pointerEvents: "none" },
962
985
  {
963
986
  backgroundColor: theme.colors.eventBackground,
@@ -972,10 +995,15 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
972
995
  });
973
996
  }
974
997
  const TimetablePage = (0, react.memo)(TimetablePageInner);
975
- 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 }) {
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 }) {
976
999
  const clampedMinHour = Math.max(0, Math.min(minHour, HOURS_PER_DAY - 1));
977
1000
  const clampedMaxHour = Math.max(clampedMinHour + 1, Math.min(maxHour, HOURS_PER_DAY));
978
1001
  const hourColumnWidth = hideHours ? 0 : hourColumnWidthProp;
1002
+ const labeledRenderEvent = (0, react.useMemo)(() => require_MonthList.withEventAccessibilityLabel(renderEvent, eventAccessibilityLabel, ampm), [
1003
+ renderEvent,
1004
+ eventAccessibilityLabel,
1005
+ ampm
1006
+ ]);
979
1007
  const { width, height } = (0, react_native.useWindowDimensions)();
980
1008
  const listRef = (0, react.useRef)(null);
981
1009
  const containerRef = (0, react.useRef)(null);
@@ -985,7 +1013,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
985
1013
  const [measured, setMeasured] = (0, react.useState)(false);
986
1014
  const weekAnchored = mode === "week" || mode === "custom" && weekEndsOn != null;
987
1015
  const step = weekAnchored ? 7 : (0, _super_calendar_core.viewDayCount)(mode, numberOfDays);
988
- const seedDefaultY = Math.max(0, scrollOffsetMinutes / MINUTES_PER_HOUR - clampedMinHour) * hourHeight;
1016
+ const seedDefaultY = Math.max(0, scrollOffsetMinutes / MINUTES_PER_HOUR$1 - clampedMinHour) * hourHeight;
989
1017
  const scrollY = (0, react_native_reanimated.useSharedValue)(seedDefaultY);
990
1018
  const offsetSeedRef = (0, react.useRef)(null);
991
1019
  const captureOffsetSeed = (0, react.useCallback)((y) => {
@@ -1167,7 +1195,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1167
1195
  minHourHeight,
1168
1196
  maxHourHeight,
1169
1197
  showNowIndicator,
1170
- renderEvent,
1198
+ renderEvent: labeledRenderEvent,
1171
1199
  keyExtractor,
1172
1200
  snapMinutes: Math.max(1, dragStepMinutes),
1173
1201
  showDragHandle,
@@ -1209,7 +1237,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1209
1237
  minHourHeight,
1210
1238
  maxHourHeight,
1211
1239
  showNowIndicator,
1212
- renderEvent,
1240
+ labeledRenderEvent,
1213
1241
  keyExtractor,
1214
1242
  dragStepMinutes,
1215
1243
  showDragHandle,
@@ -1227,7 +1255,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1227
1255
  }), [events, activeIndex]);
1228
1256
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1229
1257
  ref: containerRef,
1230
- style: styles.container,
1258
+ style: styles$1.container,
1231
1259
  children: [
1232
1260
  renderHeader ? renderHeader(headerDays) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultHeader, {
1233
1261
  days: headerDays,
@@ -1236,13 +1264,14 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1236
1264
  hourColumnWidth,
1237
1265
  showWeekNumber,
1238
1266
  weekNumberPrefix,
1267
+ weekdayFormat,
1239
1268
  locale,
1240
1269
  activeDate,
1241
1270
  onPressDateHeader
1242
1271
  }),
1243
1272
  headerComponent,
1244
1273
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1245
- style: styles.pager,
1274
+ style: styles$1.pager,
1246
1275
  onLayout: (event) => {
1247
1276
  setPageHeight(event.nativeEvent.layout.height);
1248
1277
  setContainerWidth(event.nativeEvent.layout.width);
@@ -1250,7 +1279,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1250
1279
  },
1251
1280
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
1252
1281
  ref: listRef,
1253
- style: isWeb ? [styles.pagerList, styles.webNoScroll] : styles.pagerList,
1282
+ style: isWeb ? [styles$1.pagerList, styles$1.webNoScroll] : styles$1.pagerList,
1254
1283
  data: pageDates,
1255
1284
  extraData: listExtraData,
1256
1285
  horizontal: true,
@@ -1292,13 +1321,13 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
1292
1321
  * ```
1293
1322
  */
1294
1323
  const TimeGrid = (0, react.memo)(TimeGridInner);
1295
- const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, weekNumberPrefix = "W", locale, activeDate, onPressDateHeader }) => {
1324
+ const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, weekNumberPrefix = "W", weekdayFormat, locale, activeDate, onPressDateHeader }) => {
1296
1325
  const theme = require_MonthList.useCalendarTheme();
1297
1326
  const dayWidth = (width - hourColumnWidth) / days.length;
1298
1327
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1299
- style: [styles.headerRow, { borderBottomColor: theme.colors.gridLine }],
1328
+ style: [styles$1.headerRow, { borderBottomColor: theme.colors.gridLine }],
1300
1329
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1301
- style: [styles.weekNumberGutter, { width: hourColumnWidth }],
1330
+ style: [styles$1.weekNumberGutter, { width: hourColumnWidth }],
1302
1331
  children: showWeekNumber && hourColumnWidth > 0 && days[0] ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1303
1332
  style: [theme.text.hourLabel, { color: theme.colors.textMuted }],
1304
1333
  allowFontScaling: false,
@@ -1308,29 +1337,40 @@ const DefaultHeader = ({ days, mode, width, hourColumnWidth, showWeekNumber, wee
1308
1337
  day,
1309
1338
  mode,
1310
1339
  width: dayWidth,
1340
+ weekdayFormat,
1311
1341
  locale,
1312
1342
  activeDate,
1313
1343
  onPressDateHeader
1314
1344
  }, day.toISOString()))]
1315
1345
  });
1316
1346
  };
1317
- const DayHeader = ({ day, width, locale, activeDate, onPressDateHeader }) => {
1347
+ const DayHeader = ({ day, width, weekdayFormat = "short", locale, activeDate, onPressDateHeader }) => {
1318
1348
  const theme = require_MonthList.useCalendarTheme();
1319
1349
  const isToday = (0, _super_calendar_core.getIsToday)(day);
1320
1350
  const isHighlighted = activeDate ? (0, _super_calendar_core.isSameCalendarDay)(day, activeDate) : isToday;
1321
1351
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Pressable, {
1322
- style: [styles.dayHeader, { width }],
1352
+ style: [
1353
+ styles$1.dayHeader,
1354
+ { width },
1355
+ theme.containers.columnHeader
1356
+ ],
1323
1357
  onPress: onPressDateHeader ? () => onPressDateHeader(day) : void 0,
1324
1358
  disabled: !onPressDateHeader,
1325
1359
  accessibilityRole: onPressDateHeader ? "button" : void 0,
1360
+ accessibilityLabel: onPressDateHeader ? (0, date_fns.format)(day, "EEEE d MMMM", { locale }) : void 0,
1326
1361
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1327
- style: [styles.dayHeaderWeekday, { color: theme.colors.textMuted }],
1362
+ style: [{ color: theme.colors.textMuted }, theme.text.columnHeaderWeekday],
1328
1363
  allowFontScaling: false,
1329
- children: (0, date_fns.format)(day, "EEE", { locale })
1364
+ children: (0, date_fns.format)(day, (0, _super_calendar_core.weekdayFormatToken)(weekdayFormat), { locale })
1330
1365
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1331
- style: [styles.dayHeaderBadge, isHighlighted && { backgroundColor: theme.colors.todayBackground }],
1366
+ testID: "column-header-badge",
1367
+ style: [
1368
+ styles$1.dayHeaderBadge,
1369
+ theme.containers.columnHeaderBadge,
1370
+ isHighlighted && { backgroundColor: theme.colors.todayBackground }
1371
+ ],
1332
1372
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1333
- style: [styles.dayHeaderNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }],
1373
+ style: [theme.text.dayNumber, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }],
1334
1374
  allowFontScaling: false,
1335
1375
  ...isToday && { accessibilityLabel: `Today, ${day.getDate()}` },
1336
1376
  children: day.getDate()
@@ -1338,7 +1378,7 @@ const DayHeader = ({ day, width, locale, activeDate, onPressDateHeader }) => {
1338
1378
  })]
1339
1379
  });
1340
1380
  };
1341
- const styles = react_native.StyleSheet.create({
1381
+ const styles$1 = react_native.StyleSheet.create({
1342
1382
  pager: { flex: 1 },
1343
1383
  pagerList: { flex: 1 },
1344
1384
  container: { flex: 1 },
@@ -1356,10 +1396,6 @@ const styles = react_native.StyleSheet.create({
1356
1396
  gap: 2,
1357
1397
  paddingVertical: 6
1358
1398
  },
1359
- dayHeaderWeekday: {
1360
- fontSize: 11,
1361
- fontWeight: "600"
1362
- },
1363
1399
  dayHeaderBadge: {
1364
1400
  width: 28,
1365
1401
  height: 28,
@@ -1367,10 +1403,6 @@ const styles = react_native.StyleSheet.create({
1367
1403
  justifyContent: "center",
1368
1404
  alignItems: "center"
1369
1405
  },
1370
- dayHeaderNumber: {
1371
- fontSize: 15,
1372
- fontWeight: "600"
1373
- },
1374
1406
  content: {
1375
1407
  width: "100%",
1376
1408
  position: "relative"
@@ -1480,7 +1512,7 @@ function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1480
1512
  * }
1481
1513
  * ```
1482
1514
  */
1483
- 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 }) {
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 }) {
1484
1516
  const mergedTheme = (0, react.useMemo)(() => require_MonthList.mergeTheme(theme), [theme]);
1485
1517
  const internalCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
1486
1518
  const cellHeight = cellHeightProp ?? internalCellHeight;
@@ -1502,7 +1534,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1502
1534
  weekEndsOn
1503
1535
  ]);
1504
1536
  const resolvedRenderEvent = (0, react.useMemo)(() => {
1505
- if (eventCellStyle == null && ampm == null && showTime == null && ellipsizeTitle == null && allDayLabel == null) return renderEvent;
1537
+ if (eventCellStyle == null && ampm == null && showTime == null && ellipsizeTitle == null && allDayLabel == null && eventAccessibilityLabel == null) return renderEvent;
1506
1538
  const Base = renderEvent;
1507
1539
  return function StyledEvent(props) {
1508
1540
  const cellStyle = typeof eventCellStyle === "function" ? eventCellStyle(props.event) : eventCellStyle;
@@ -1512,7 +1544,12 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1512
1544
  ampm,
1513
1545
  showTime,
1514
1546
  ellipsizeTitle,
1515
- allDayLabel
1547
+ allDayLabel,
1548
+ accessibilityLabel: eventAccessibilityLabel ? eventAccessibilityLabel(props.event, {
1549
+ mode: props.mode,
1550
+ isAllDay: props.isAllDay ?? false,
1551
+ ampm: ampm ?? false
1552
+ }) : props.accessibilityLabel
1516
1553
  });
1517
1554
  };
1518
1555
  }, [
@@ -1521,7 +1558,8 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1521
1558
  ampm,
1522
1559
  showTime,
1523
1560
  ellipsizeTitle,
1524
- allDayLabel
1561
+ allDayLabel,
1562
+ eventAccessibilityLabel
1525
1563
  ]);
1526
1564
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MonthList.CalendarThemeProvider, {
1527
1565
  value: mergedTheme,
@@ -1530,6 +1568,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1530
1568
  events,
1531
1569
  maxVisibleEventCount,
1532
1570
  weekStartsOn,
1571
+ weekdayFormat,
1533
1572
  locale,
1534
1573
  sortedMonthView,
1535
1574
  moreLabel,
@@ -1570,6 +1609,7 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1570
1609
  cellHeight,
1571
1610
  hourHeight,
1572
1611
  weekStartsOn,
1612
+ weekdayFormat,
1573
1613
  renderEvent: resolvedRenderEvent,
1574
1614
  keyExtractor,
1575
1615
  scrollOffsetMinutes,
@@ -1613,6 +1653,326 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1613
1653
  });
1614
1654
  }
1615
1655
  //#endregion
1656
+ //#region src/components/ResourceTimeline.tsx
1657
+ const MOVE_ACTIVATE_MS = 250;
1658
+ const MINUTES_PER_HOUR = 60;
1659
+ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
1660
+ function DefaultBar({ event, width }) {
1661
+ const theme = require_MonthList.useCalendarTheme();
1662
+ const time = (0, _super_calendar_core.eventTimeLabel)({
1663
+ mode: "day",
1664
+ isAllDay: false,
1665
+ start: event.start,
1666
+ end: event.end,
1667
+ ampm: false,
1668
+ showTime: true
1669
+ });
1670
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1671
+ style: [
1672
+ styles.bar,
1673
+ { backgroundColor: theme.colors.eventBackground },
1674
+ theme.containers.timeGridEvent
1675
+ ],
1676
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1677
+ numberOfLines: 1,
1678
+ style: [theme.text.eventTitle, { color: theme.colors.eventText }],
1679
+ allowFontScaling: false,
1680
+ children: event.title
1681
+ }), time && width > 56 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1682
+ numberOfLines: 1,
1683
+ style: [styles.barTime, { color: theme.colors.eventText }],
1684
+ allowFontScaling: false,
1685
+ children: time
1686
+ }) : null]
1687
+ });
1688
+ }
1689
+ function ResourceBar({ pe, left, width, laneHeight, hourWidth, snapMinutes, Renderer, onPress, onDragEvent, theme }) {
1690
+ const moveX = (0, react_native_reanimated.useSharedValue)(0);
1691
+ const resizeW = (0, react_native_reanimated.useSharedValue)(0);
1692
+ const latest = (0, react.useRef)({
1693
+ event: pe.event,
1694
+ onDragEvent
1695
+ });
1696
+ latest.current = {
1697
+ event: pe.event,
1698
+ onDragEvent
1699
+ };
1700
+ const draggable = !pe.event.disabled;
1701
+ (0, react.useEffect)(() => {
1702
+ moveX.value = 0;
1703
+ resizeW.value = 0;
1704
+ }, [
1705
+ pe.startHours,
1706
+ pe.durationHours,
1707
+ moveX,
1708
+ resizeW
1709
+ ]);
1710
+ const snapBack = (0, react.useCallback)(() => {
1711
+ moveX.value = 0;
1712
+ resizeW.value = 0;
1713
+ }, [moveX, resizeW]);
1714
+ const commit = (0, react.useCallback)((deltaStartMin, deltaEndMin) => {
1715
+ const { event, onDragEvent: handler } = latest.current;
1716
+ const next = (0, _super_calendar_core.resolveDraggedBounds)(event.start, event.end, deltaStartMin, deltaEndMin, snapMinutes);
1717
+ if (!next) {
1718
+ snapBack();
1719
+ return;
1720
+ }
1721
+ if (handler(event, next.start, next.end) === false) snapBack();
1722
+ }, [snapMinutes, snapBack]);
1723
+ const barStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
1724
+ transform: [{ translateX: moveX.value }],
1725
+ width: Math.max(width + resizeW.value, 2)
1726
+ }), [width]);
1727
+ const moveGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(draggable).activateAfterLongPress(MOVE_ACTIVATE_MS).onUpdate((e) => {
1728
+ moveX.value = e.translationX;
1729
+ }).onEnd((e) => {
1730
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(e.translationX, hourWidth, snapMinutes);
1731
+ if (delta === 0) {
1732
+ moveX.value = 0;
1733
+ return;
1734
+ }
1735
+ moveX.value = delta / MINUTES_PER_HOUR * hourWidth;
1736
+ (0, react_native_reanimated.runOnJS)(commit)(delta, delta);
1737
+ }), [
1738
+ draggable,
1739
+ hourWidth,
1740
+ snapMinutes,
1741
+ moveX,
1742
+ commit
1743
+ ]);
1744
+ const resizeGesture = (0, react.useMemo)(() => react_native_gesture_handler.Gesture.Pan().enabled(draggable).onUpdate((e) => {
1745
+ resizeW.value = e.translationX;
1746
+ }).onEnd((e) => {
1747
+ const delta = (0, _super_calendar_core.snapDeltaMinutes)(e.translationX, hourWidth, snapMinutes);
1748
+ if (delta === 0) {
1749
+ resizeW.value = 0;
1750
+ return;
1751
+ }
1752
+ resizeW.value = delta / MINUTES_PER_HOUR * hourWidth;
1753
+ (0, react_native_reanimated.runOnJS)(commit)(0, delta);
1754
+ }), [
1755
+ draggable,
1756
+ hourWidth,
1757
+ snapMinutes,
1758
+ resizeW,
1759
+ commit
1760
+ ]);
1761
+ 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],
1769
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
1770
+ gesture: moveGesture,
1771
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
1772
+ onPress,
1773
+ accessibilityRole: "button",
1774
+ accessibilityLabel: pe.event.title,
1775
+ style: styles.fill,
1776
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
1777
+ event: pe.event,
1778
+ width,
1779
+ onPress
1780
+ })
1781
+ })
1782
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
1783
+ gesture: resizeGesture,
1784
+ 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}`
1788
+ })
1789
+ })]
1790
+ });
1791
+ }
1792
+ /**
1793
+ * A horizontal resource timeline: rows are resources (rooms, people, machines)
1794
+ * and the x-axis is one day's hours. Events sit in their resource's row, and
1795
+ * overlapping events in the same row stack into sub-lanes (via the shared
1796
+ * `layoutDayEvents`). The grid scrolls horizontally when the axis is wider than
1797
+ * the screen. Pass `onDragEvent` to enable long-press drag-to-move and edge
1798
+ * resize along the time axis. Read the theme from context — wrap in
1799
+ * `CalendarThemeProvider` (or render inside `<Calendar>`) to restyle.
1800
+ *
1801
+ * @example
1802
+ * ```tsx
1803
+ * <ResourceTimeline
1804
+ * date={new Date()}
1805
+ * resources={[{ id: "a", title: "Room A" }, { id: "b", title: "Room B" }]}
1806
+ * events={events} // each event carries a `resourceId`
1807
+ * />
1808
+ * ```
1809
+ */
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 }) {
1811
+ const theme = require_MonthList.useCalendarTheme();
1812
+ const Renderer = renderEvent ?? DefaultBar;
1813
+ const hours = (0, react.useMemo)(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
1814
+ const trackWidth = (endHour - startHour) * hourWidth;
1815
+ const byResource = (0, react.useMemo)(() => {
1816
+ const map = /* @__PURE__ */ new Map();
1817
+ for (const resource of resources) {
1818
+ const own = events.filter((event) => resourceId(event) === resource.id);
1819
+ map.set(resource.id, (0, _super_calendar_core.layoutDayEvents)(own, date));
1820
+ }
1821
+ return map;
1822
+ }, [
1823
+ resources,
1824
+ events,
1825
+ resourceId,
1826
+ date
1827
+ ]);
1828
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
1829
+ horizontal: true,
1830
+ showsHorizontalScrollIndicator: true,
1831
+ style: styles.root,
1832
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1833
+ style: { width: labelWidth + trackWidth },
1834
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1835
+ style: [styles.header, { borderBottomColor: theme.colors.gridLine }],
1836
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: { width: labelWidth } }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1837
+ style: {
1838
+ width: trackWidth,
1839
+ height: 24
1840
+ },
1841
+ children: hours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1842
+ allowFontScaling: false,
1843
+ style: [styles.hourTick, {
1844
+ left: (h - startHour) * hourWidth,
1845
+ color: theme.colors.textMuted
1846
+ }],
1847
+ children: (0, _super_calendar_core.formatHour)(h, { ampm })
1848
+ }, h))
1849
+ })]
1850
+ }), resources.map((resource) => {
1851
+ const positioned = byResource.get(resource.id) ?? [];
1852
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1853
+ style: [
1854
+ styles.row,
1855
+ {
1856
+ height: rowHeight,
1857
+ borderBottomColor: theme.colors.gridLine
1858
+ },
1859
+ theme.containers.resourceRow
1860
+ ],
1861
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1862
+ style: [
1863
+ styles.label,
1864
+ {
1865
+ width: labelWidth,
1866
+ borderRightColor: theme.colors.gridLine
1867
+ },
1868
+ theme.containers.resourceLabel
1869
+ ],
1870
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
1871
+ numberOfLines: 1,
1872
+ style: { color: theme.colors.text },
1873
+ allowFontScaling: false,
1874
+ children: resource.title ?? resource.id
1875
+ })
1876
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
1877
+ style: { width: trackWidth },
1878
+ children: [hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
1879
+ pointerEvents: "none",
1880
+ style: [styles.gridLine, {
1881
+ left: (h - startHour) * hourWidth,
1882
+ backgroundColor: theme.colors.gridLine
1883
+ }]
1884
+ }, h)), positioned.map((pe, idx) => {
1885
+ const left = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourWidth;
1886
+ const right = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourWidth;
1887
+ const width = Math.max(right - left, 2);
1888
+ const laneHeight = rowHeight / pe.columns;
1889
+ const onPress = () => onPressEvent?.(pe.event);
1890
+ if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
1891
+ pe,
1892
+ left,
1893
+ width,
1894
+ laneHeight,
1895
+ hourWidth,
1896
+ snapMinutes: dragStepMinutes,
1897
+ Renderer,
1898
+ onPress,
1899
+ onDragEvent,
1900
+ theme
1901
+ }, idx);
1902
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
1903
+ onPress,
1904
+ accessibilityRole: "button",
1905
+ accessibilityLabel: pe.event.title,
1906
+ style: {
1907
+ position: "absolute",
1908
+ left,
1909
+ width,
1910
+ top: pe.column * laneHeight,
1911
+ height: laneHeight,
1912
+ padding: 1
1913
+ },
1914
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
1915
+ event: pe.event,
1916
+ width,
1917
+ onPress
1918
+ })
1919
+ }, idx);
1920
+ })]
1921
+ })]
1922
+ }, resource.id);
1923
+ })]
1924
+ })
1925
+ });
1926
+ }
1927
+ const styles = react_native.StyleSheet.create({
1928
+ root: { flexGrow: 0 },
1929
+ header: {
1930
+ flexDirection: "row",
1931
+ borderBottomWidth: react_native.StyleSheet.hairlineWidth
1932
+ },
1933
+ hourTick: {
1934
+ position: "absolute",
1935
+ top: 4,
1936
+ fontSize: 10
1937
+ },
1938
+ row: {
1939
+ flexDirection: "row",
1940
+ borderBottomWidth: react_native.StyleSheet.hairlineWidth
1941
+ },
1942
+ label: {
1943
+ justifyContent: "center",
1944
+ paddingHorizontal: 10,
1945
+ borderRightWidth: react_native.StyleSheet.hairlineWidth
1946
+ },
1947
+ gridLine: {
1948
+ position: "absolute",
1949
+ top: 0,
1950
+ bottom: 0,
1951
+ width: react_native.StyleSheet.hairlineWidth
1952
+ },
1953
+ bar: {
1954
+ flex: 1,
1955
+ borderRadius: 6,
1956
+ paddingHorizontal: 6,
1957
+ paddingVertical: 2,
1958
+ overflow: "hidden"
1959
+ },
1960
+ barTime: {
1961
+ fontSize: 11,
1962
+ opacity: .75
1963
+ },
1964
+ fill: { flex: 1 },
1965
+ resizeGrip: {
1966
+ position: "absolute",
1967
+ right: 1,
1968
+ top: "30%",
1969
+ bottom: "30%",
1970
+ width: 4,
1971
+ borderRadius: 2,
1972
+ opacity: .5
1973
+ }
1974
+ });
1975
+ //#endregion
1616
1976
  exports.Agenda = Agenda;
1617
1977
  exports.Calendar = Calendar;
1618
1978
  exports.CalendarThemeProvider = require_MonthList.CalendarThemeProvider;
@@ -1622,6 +1982,7 @@ exports.DefaultMonthEvent = require_MonthList.DefaultMonthEvent;
1622
1982
  exports.MonthList = require_MonthList.MonthList;
1623
1983
  exports.MonthPager = require_MonthList.MonthPager;
1624
1984
  exports.MonthView = require_MonthList.MonthView;
1985
+ exports.ResourceTimeline = ResourceTimeline;
1625
1986
  exports.TimeGrid = TimeGrid;
1626
1987
  Object.defineProperty(exports, "buildMonthGrid", {
1627
1988
  enumerable: true,
@@ -1747,3 +2108,9 @@ Object.defineProperty(exports, "useMonthGrid", {
1747
2108
  return _super_calendar_core.useMonthGrid;
1748
2109
  }
1749
2110
  });
2111
+ Object.defineProperty(exports, "weekdayFormatToken", {
2112
+ enumerable: true,
2113
+ get: function() {
2114
+ return _super_calendar_core.weekdayFormatToken;
2115
+ }
2116
+ });