@super-calendar/native 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +27 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.js +296 -102
- package/dist/index.mjs +296 -102
- package/package.json +2 -2
- package/src/components/ResourceTimeline.tsx +305 -0
package/dist/index.d.mts
CHANGED
|
@@ -465,12 +465,38 @@ interface ResourceTimelineProps<T = unknown> {
|
|
|
465
465
|
renderEvent?: ComponentType<ResourceEventArgs<T>>;
|
|
466
466
|
/** Tap an event. */
|
|
467
467
|
onPressEvent?: (event: CalendarEvent$1<T>) => void;
|
|
468
|
+
/**
|
|
469
|
+
* Long-press an event. When `onDragEvent` is also set, a long-press picks the
|
|
470
|
+
* bar up to move instead, so this fires only for non-draggable bars.
|
|
471
|
+
*/
|
|
472
|
+
onLongPressEvent?: (event: CalendarEvent$1<T>) => void;
|
|
468
473
|
/**
|
|
469
474
|
* Enables drag-to-move and edge-resize along the time axis: long-press a bar to
|
|
470
475
|
* move it, or drag its right edge to resize. Called with the proposed new
|
|
471
476
|
* start/end; return `false` to reject the drop (it snaps back).
|
|
472
477
|
*/
|
|
473
478
|
onDragEvent?: (event: CalendarEvent$1<T>, start: Date, end: Date) => void | boolean;
|
|
479
|
+
/** Tap empty lane space; called with the snapped time and the lane's resource. */
|
|
480
|
+
onPressCell?: (at: Date, resource: Resource) => void;
|
|
481
|
+
/**
|
|
482
|
+
* Long-press empty lane space. When `onCreateEvent` is also set, the long-press
|
|
483
|
+
* starts the create drag instead, so this fires only without it.
|
|
484
|
+
*/
|
|
485
|
+
onLongPressCell?: (at: Date, resource: Resource) => void;
|
|
486
|
+
/**
|
|
487
|
+
* Long-press empty lane space, then drag along the time axis to sweep out a new
|
|
488
|
+
* event; called with the swept start/end and the lane's resource.
|
|
489
|
+
*/
|
|
490
|
+
onCreateEvent?: (start: Date, end: Date, resource: Resource) => void;
|
|
491
|
+
/**
|
|
492
|
+
* Shade the hours outside this window, per lane. Same shape as the Calendar's
|
|
493
|
+
* `businessHours` plus the lane's resource, so per-resource opening hours work
|
|
494
|
+
* (return `null` for a fully closed lane). A date-only function is accepted.
|
|
495
|
+
*/
|
|
496
|
+
businessHours?: (date: Date, resource: Resource) => {
|
|
497
|
+
start: number;
|
|
498
|
+
end: number;
|
|
499
|
+
} | null;
|
|
474
500
|
/** Snap dragged events to this many minutes (default 15). */
|
|
475
501
|
dragStepMinutes?: number;
|
|
476
502
|
}
|
|
@@ -492,6 +518,6 @@ interface ResourceTimelineProps<T = unknown> {
|
|
|
492
518
|
* />
|
|
493
519
|
* ```
|
|
494
520
|
*/
|
|
495
|
-
declare function ResourceTimeline<T = unknown>({ date, orientation, resources, events, resourceId, startHour, endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm, renderEvent, onPressEvent, onDragEvent, dragStepMinutes }: ResourceTimelineProps<T>): ReactElement;
|
|
521
|
+
declare function ResourceTimeline<T = unknown>({ date, orientation, resources, events, resourceId, startHour, endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm, renderEvent, onPressEvent, onLongPressEvent, onDragEvent, onPressCell, onLongPressCell, onCreateEvent, businessHours, dragStepMinutes }: ResourceTimelineProps<T>): ReactElement;
|
|
496
522
|
//#endregion
|
|
497
523
|
export { Agenda, type AgendaProps, type AgendaSlot, type BusinessHours, Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarSlot, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultEvent, DefaultMonthEvent, type EventAccessibilityLabelContext, type EventAccessibilityLabeler, type EventDragHandler, type EventDragStartHandler, type EventKeyExtractor, type HourRenderer, type ICalEvent, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, type MonthListSlot, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type MonthViewSlot, type PartialCalendarTheme, type PositionedEvent, type RecurrenceFrequency, type RecurrenceRule, type RenderEvent, type RenderEventArgs, type ResolvedSlot, type Resource, type ResourceEventArgs, ResourceTimeline, type ResourceTimelineProps, type SlotDefault, type SlotStyleProps, TimeGrid, type TimeGridMode, type TimeGridProps, type TimeGridSlot, type ToICalendarOptions, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, type WeekdayFormat, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
|
package/dist/index.d.ts
CHANGED
|
@@ -465,12 +465,38 @@ interface ResourceTimelineProps<T = unknown> {
|
|
|
465
465
|
renderEvent?: ComponentType<ResourceEventArgs<T>>;
|
|
466
466
|
/** Tap an event. */
|
|
467
467
|
onPressEvent?: (event: CalendarEvent$1<T>) => void;
|
|
468
|
+
/**
|
|
469
|
+
* Long-press an event. When `onDragEvent` is also set, a long-press picks the
|
|
470
|
+
* bar up to move instead, so this fires only for non-draggable bars.
|
|
471
|
+
*/
|
|
472
|
+
onLongPressEvent?: (event: CalendarEvent$1<T>) => void;
|
|
468
473
|
/**
|
|
469
474
|
* Enables drag-to-move and edge-resize along the time axis: long-press a bar to
|
|
470
475
|
* move it, or drag its right edge to resize. Called with the proposed new
|
|
471
476
|
* start/end; return `false` to reject the drop (it snaps back).
|
|
472
477
|
*/
|
|
473
478
|
onDragEvent?: (event: CalendarEvent$1<T>, start: Date, end: Date) => void | boolean;
|
|
479
|
+
/** Tap empty lane space; called with the snapped time and the lane's resource. */
|
|
480
|
+
onPressCell?: (at: Date, resource: Resource) => void;
|
|
481
|
+
/**
|
|
482
|
+
* Long-press empty lane space. When `onCreateEvent` is also set, the long-press
|
|
483
|
+
* starts the create drag instead, so this fires only without it.
|
|
484
|
+
*/
|
|
485
|
+
onLongPressCell?: (at: Date, resource: Resource) => void;
|
|
486
|
+
/**
|
|
487
|
+
* Long-press empty lane space, then drag along the time axis to sweep out a new
|
|
488
|
+
* event; called with the swept start/end and the lane's resource.
|
|
489
|
+
*/
|
|
490
|
+
onCreateEvent?: (start: Date, end: Date, resource: Resource) => void;
|
|
491
|
+
/**
|
|
492
|
+
* Shade the hours outside this window, per lane. Same shape as the Calendar's
|
|
493
|
+
* `businessHours` plus the lane's resource, so per-resource opening hours work
|
|
494
|
+
* (return `null` for a fully closed lane). A date-only function is accepted.
|
|
495
|
+
*/
|
|
496
|
+
businessHours?: (date: Date, resource: Resource) => {
|
|
497
|
+
start: number;
|
|
498
|
+
end: number;
|
|
499
|
+
} | null;
|
|
474
500
|
/** Snap dragged events to this many minutes (default 15). */
|
|
475
501
|
dragStepMinutes?: number;
|
|
476
502
|
}
|
|
@@ -492,6 +518,6 @@ interface ResourceTimelineProps<T = unknown> {
|
|
|
492
518
|
* />
|
|
493
519
|
* ```
|
|
494
520
|
*/
|
|
495
|
-
declare function ResourceTimeline<T = unknown>({ date, orientation, resources, events, resourceId, startHour, endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm, renderEvent, onPressEvent, onDragEvent, dragStepMinutes }: ResourceTimelineProps<T>): ReactElement;
|
|
521
|
+
declare function ResourceTimeline<T = unknown>({ date, orientation, resources, events, resourceId, startHour, endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm, renderEvent, onPressEvent, onLongPressEvent, onDragEvent, onPressCell, onLongPressCell, onCreateEvent, businessHours, dragStepMinutes }: ResourceTimelineProps<T>): ReactElement;
|
|
496
522
|
//#endregion
|
|
497
523
|
export { Agenda, type AgendaProps, type AgendaSlot, type BusinessHours, Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarSlot, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultEvent, DefaultMonthEvent, type EventAccessibilityLabelContext, type EventAccessibilityLabeler, type EventDragHandler, type EventDragStartHandler, type EventKeyExtractor, type HourRenderer, type ICalEvent, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, type MonthListSlot, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type MonthViewSlot, type PartialCalendarTheme, type PositionedEvent, type RecurrenceFrequency, type RecurrenceRule, type RenderEvent, type RenderEventArgs, type ResolvedSlot, type Resource, type ResourceEventArgs, ResourceTimeline, type ResourceTimelineProps, type SlotDefault, type SlotStyleProps, TimeGrid, type TimeGridMode, type TimeGridProps, type TimeGridSlot, type ToICalendarOptions, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, type WeekdayFormat, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
|
package/dist/index.js
CHANGED
|
@@ -402,7 +402,7 @@ const styles$2 = react_native.StyleSheet.create({
|
|
|
402
402
|
});
|
|
403
403
|
//#endregion
|
|
404
404
|
//#region src/components/TimeGrid.tsx
|
|
405
|
-
const isWeb = react_native.Platform.OS === "web";
|
|
405
|
+
const isWeb$1 = react_native.Platform.OS === "web";
|
|
406
406
|
const MINUTES_PER_HOUR$1 = 60;
|
|
407
407
|
const HOURS_PER_DAY = 24;
|
|
408
408
|
const MINUTES_PER_DAY = MINUTES_PER_HOUR$1 * HOURS_PER_DAY;
|
|
@@ -417,7 +417,7 @@ const MIN_EVENT_HEIGHT = 32;
|
|
|
417
417
|
const EVENT_GAP = 2;
|
|
418
418
|
const DRAG_ACTIVATE_MS = 300;
|
|
419
419
|
const MOVE_ACTIVATE_MS$1 = 500;
|
|
420
|
-
const DRAG_ACTIVATE_PX = 8;
|
|
420
|
+
const DRAG_ACTIVATE_PX$1 = 8;
|
|
421
421
|
const RESIZE_HANDLE_HEIGHT = 14;
|
|
422
422
|
const DEFAULT_DRAG_STEP_MINUTES = 15;
|
|
423
423
|
const HOUR_LABEL_TOP_INSET = 12;
|
|
@@ -516,7 +516,7 @@ function AnimatedEventBox({ positioned, cellHeight, minHour, left, width, dayWid
|
|
|
516
516
|
const totalDelta = minuteDelta + dayDelta * MINUTES_PER_DAY;
|
|
517
517
|
(0, react_native_reanimated.runOnJS)(commitDrag)(totalDelta, totalDelta);
|
|
518
518
|
});
|
|
519
|
-
return isWeb ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]).activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS$1);
|
|
519
|
+
return isWeb$1 ? pan.activeOffsetX([-8, DRAG_ACTIVATE_PX$1]).activeOffsetY([-8, DRAG_ACTIVATE_PX$1]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS$1);
|
|
520
520
|
}, [
|
|
521
521
|
draggable,
|
|
522
522
|
snapMinutes,
|
|
@@ -732,14 +732,14 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
|
|
|
732
732
|
},
|
|
733
733
|
onEndDrag: (event) => {
|
|
734
734
|
isDragging.value = false;
|
|
735
|
-
if (!isWeb && isActiveShared.value) {
|
|
735
|
+
if (!isWeb$1 && isActiveShared.value) {
|
|
736
736
|
scrollY.value = event.contentOffset.y;
|
|
737
737
|
(0, react_native_reanimated.runOnJS)(onSettleOffset)(event.contentOffset.y);
|
|
738
738
|
}
|
|
739
739
|
},
|
|
740
740
|
onMomentumEnd: (event) => {
|
|
741
741
|
isDragging.value = false;
|
|
742
|
-
if (!isWeb && isActiveShared.value) {
|
|
742
|
+
if (!isWeb$1 && isActiveShared.value) {
|
|
743
743
|
scrollY.value = event.contentOffset.y;
|
|
744
744
|
(0, react_native_reanimated.runOnJS)(onSettleOffset)(event.contentOffset.y);
|
|
745
745
|
}
|
|
@@ -749,7 +749,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
|
|
|
749
749
|
if (!isActiveShared.value && current !== previous) (0, react_native_reanimated.scrollTo)(scrollRef, 0, current, false);
|
|
750
750
|
});
|
|
751
751
|
(0, react_native_reanimated.useAnimatedReaction)(() => isActiveShared.value, (active, previous) => {
|
|
752
|
-
if (isWeb || !active || active === previous) return;
|
|
752
|
+
if (isWeb$1 || !active || active === previous) return;
|
|
753
753
|
(0, react_native_reanimated.scrollTo)(scrollRef, 0, scrollY.value, false);
|
|
754
754
|
});
|
|
755
755
|
const days = (0, react.useMemo)(() => (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, isRTL, weekEndsOn), [
|
|
@@ -872,7 +872,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
|
|
|
872
872
|
if (createCancelled.value) return;
|
|
873
873
|
(0, react_native_reanimated.runOnJS)(commitCreate)(createStartY.value, createStartY.value + event.translationY, createDayIndex.value);
|
|
874
874
|
});
|
|
875
|
-
return isWeb ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(DRAG_ACTIVATE_MS);
|
|
875
|
+
return isWeb$1 ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX$1]) : pan.activateAfterLongPress(DRAG_ACTIVATE_MS);
|
|
876
876
|
}, [
|
|
877
877
|
createEnabled,
|
|
878
878
|
dayCount,
|
|
@@ -891,7 +891,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
|
|
|
891
891
|
createCancelled
|
|
892
892
|
]);
|
|
893
893
|
const backgroundGesture = (0, react.useMemo)(() => {
|
|
894
|
-
const tap = isWeb && onPressCell != null ? react_native_gesture_handler.Gesture.Tap().onEnd((event) => {
|
|
894
|
+
const tap = isWeb$1 && onPressCell != null ? react_native_gesture_handler.Gesture.Tap().onEnd((event) => {
|
|
895
895
|
(0, react_native_reanimated.runOnJS)(tapCell)(event.x, event.y);
|
|
896
896
|
}) : null;
|
|
897
897
|
if (createEnabled && tap) return react_native_gesture_handler.Gesture.Exclusive(createGesture, tap);
|
|
@@ -904,7 +904,7 @@ function TimetablePageInner({ mode, numberOfDays, date, events, cellHeight, hour
|
|
|
904
904
|
tapCell
|
|
905
905
|
]);
|
|
906
906
|
(0, react.useEffect)(() => {
|
|
907
|
-
if (!isWeb || !createEnabled) return;
|
|
907
|
+
if (!isWeb$1 || !createEnabled) return;
|
|
908
908
|
const doc = globalThis.document;
|
|
909
909
|
if (!doc) return;
|
|
910
910
|
const handler = (event) => {
|
|
@@ -1110,7 +1110,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
|
|
|
1110
1110
|
offsetSeedRef.current = y;
|
|
1111
1111
|
}, []);
|
|
1112
1112
|
const committedCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
|
|
1113
|
-
useWebGridZoom(isWeb, containerRef, cellHeight, committedCellHeight, minHourHeight, maxHourHeight);
|
|
1113
|
+
useWebGridZoom(isWeb$1, containerRef, cellHeight, committedCellHeight, minHourHeight, maxHourHeight);
|
|
1114
1114
|
const [anchorDate] = (0, react.useState)(date);
|
|
1115
1115
|
const anchor = (0, react.useMemo)(() => weekAnchored ? (0, date_fns.startOfWeek)(anchorDate, { weekStartsOn }) : (0, date_fns.startOfDay)(anchorDate), [
|
|
1116
1116
|
weekAnchored,
|
|
@@ -1140,7 +1140,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
|
|
|
1140
1140
|
weekEndsOn
|
|
1141
1141
|
]);
|
|
1142
1142
|
const handleViewableItemsChanged = (0, react.useCallback)((info) => {
|
|
1143
|
-
if (isWeb) return;
|
|
1143
|
+
if (isWeb$1) return;
|
|
1144
1144
|
const settled = info.viewableItems.find((token) => token.isViewable);
|
|
1145
1145
|
if (settled?.index == null) return;
|
|
1146
1146
|
if (pendingScrollIndexRef.current != null) {
|
|
@@ -1164,7 +1164,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
|
|
|
1164
1164
|
});
|
|
1165
1165
|
}, [activeIndex]);
|
|
1166
1166
|
(0, react.useEffect)(() => {
|
|
1167
|
-
if (!isWeb) return;
|
|
1167
|
+
if (!isWeb$1) return;
|
|
1168
1168
|
const root = containerRef.current;
|
|
1169
1169
|
if (!root) return;
|
|
1170
1170
|
const restoreVisiblePage = () => {
|
|
@@ -1191,7 +1191,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
|
|
|
1191
1191
|
};
|
|
1192
1192
|
}, [activeIndex, pageHeight]);
|
|
1193
1193
|
(0, react.useEffect)(() => {
|
|
1194
|
-
if (!isWeb) return;
|
|
1194
|
+
if (!isWeb$1) return;
|
|
1195
1195
|
const root = containerRef.current;
|
|
1196
1196
|
if (!root) return;
|
|
1197
1197
|
const onScrollCapture = (event) => {
|
|
@@ -1208,7 +1208,7 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
|
|
|
1208
1208
|
return () => root.removeEventListener("scroll", onScrollCapture, true);
|
|
1209
1209
|
}, []);
|
|
1210
1210
|
(0, react.useEffect)(() => {
|
|
1211
|
-
if (!isWeb) return;
|
|
1211
|
+
if (!isWeb$1) return;
|
|
1212
1212
|
const root = containerRef.current;
|
|
1213
1213
|
if (!root) return;
|
|
1214
1214
|
const lockHorizontal = () => {
|
|
@@ -1374,14 +1374,14 @@ function TimeGridInner({ mode, numberOfDays = 1, weekEndsOn, date, events, cellH
|
|
|
1374
1374
|
},
|
|
1375
1375
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react_native.LegendList, {
|
|
1376
1376
|
ref: listRef,
|
|
1377
|
-
style: isWeb ? [styles$1.pagerList, styles$1.webNoScroll] : styles$1.pagerList,
|
|
1377
|
+
style: isWeb$1 ? [styles$1.pagerList, styles$1.webNoScroll] : styles$1.pagerList,
|
|
1378
1378
|
data: pageDates,
|
|
1379
1379
|
extraData: listExtraData,
|
|
1380
1380
|
horizontal: true,
|
|
1381
1381
|
recycleItems: false,
|
|
1382
1382
|
keyExtractor: keyExtractorList,
|
|
1383
1383
|
getFixedItemSize,
|
|
1384
|
-
...isWeb ? null : {
|
|
1384
|
+
...isWeb$1 ? null : {
|
|
1385
1385
|
scrollEnabled: swipeEnabled,
|
|
1386
1386
|
pagingEnabled: !freeSwipe,
|
|
1387
1387
|
snapToIndices: freeSwipe ? snapToIndices : void 0
|
|
@@ -1795,7 +1795,9 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
|
|
|
1795
1795
|
//#endregion
|
|
1796
1796
|
//#region src/components/ResourceTimeline.tsx
|
|
1797
1797
|
const MOVE_ACTIVATE_MS = 250;
|
|
1798
|
+
const DRAG_ACTIVATE_PX = 8;
|
|
1798
1799
|
const MINUTES_PER_HOUR = 60;
|
|
1800
|
+
const isWeb = react_native.Platform.OS === "web";
|
|
1799
1801
|
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
1800
1802
|
const GUTTER_WIDTH = 56;
|
|
1801
1803
|
function DefaultBar({ event, width, height }) {
|
|
@@ -1828,7 +1830,7 @@ function DefaultBar({ event, width, height }) {
|
|
|
1828
1830
|
}) : null]
|
|
1829
1831
|
});
|
|
1830
1832
|
}
|
|
1831
|
-
function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendererSize, snapMinutes, Renderer, onPress, onDragEvent, theme }) {
|
|
1833
|
+
function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendererSize, snapMinutes, Renderer, onPress, onLongPress, onDragEvent, theme }) {
|
|
1832
1834
|
const moveX = (0, react_native_reanimated.useSharedValue)(0);
|
|
1833
1835
|
const resizeW = (0, react_native_reanimated.useSharedValue)(0);
|
|
1834
1836
|
const latest = (0, react.useRef)({
|
|
@@ -1959,6 +1961,7 @@ function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendere
|
|
|
1959
1961
|
gesture: moveGesture,
|
|
1960
1962
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
|
|
1961
1963
|
onPress,
|
|
1964
|
+
onLongPress,
|
|
1962
1965
|
accessibilityRole: "button",
|
|
1963
1966
|
accessibilityLabel: pe.event.title,
|
|
1964
1967
|
accessibilityActions: barActions,
|
|
@@ -1982,6 +1985,115 @@ function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendere
|
|
|
1982
1985
|
})]
|
|
1983
1986
|
});
|
|
1984
1987
|
}
|
|
1988
|
+
function LaneInteractionLayer({ resource, vertical, hourSize, startHour, date, snapMinutes, onPressCell, onLongPressCell, onCreateEvent, theme }) {
|
|
1989
|
+
const ghostStart = (0, react_native_reanimated.useSharedValue)(0);
|
|
1990
|
+
const ghostSize = (0, react_native_reanimated.useSharedValue)(0);
|
|
1991
|
+
const ghostVisible = (0, react_native_reanimated.useSharedValue)(0);
|
|
1992
|
+
const timeAt = (0, react.useCallback)((px) => (0, _super_calendar_core.cellRangeFromDrag)(date, px, px, hourSize, startHour, snapMinutes)?.start, [
|
|
1993
|
+
date,
|
|
1994
|
+
hourSize,
|
|
1995
|
+
startHour,
|
|
1996
|
+
snapMinutes
|
|
1997
|
+
]);
|
|
1998
|
+
const commitCreate = (0, react.useCallback)((fromPx, toPx) => {
|
|
1999
|
+
const range = (0, _super_calendar_core.cellRangeFromDrag)(date, fromPx, toPx, hourSize, startHour, snapMinutes);
|
|
2000
|
+
if (range) onCreateEvent?.(range.start, range.end, resource);
|
|
2001
|
+
}, [
|
|
2002
|
+
date,
|
|
2003
|
+
hourSize,
|
|
2004
|
+
startHour,
|
|
2005
|
+
snapMinutes,
|
|
2006
|
+
onCreateEvent,
|
|
2007
|
+
resource
|
|
2008
|
+
]);
|
|
2009
|
+
const pressAt = (0, react.useCallback)((px) => {
|
|
2010
|
+
const at = timeAt(px);
|
|
2011
|
+
if (at) onPressCell?.(at, resource);
|
|
2012
|
+
}, [
|
|
2013
|
+
timeAt,
|
|
2014
|
+
onPressCell,
|
|
2015
|
+
resource
|
|
2016
|
+
]);
|
|
2017
|
+
const laneGesture = (0, react.useMemo)(() => {
|
|
2018
|
+
const pan = onCreateEvent ? react_native_gesture_handler.Gesture.Pan().onStart((e) => {
|
|
2019
|
+
ghostStart.value = vertical ? e.y : e.x;
|
|
2020
|
+
ghostSize.value = 0;
|
|
2021
|
+
ghostVisible.value = 1;
|
|
2022
|
+
}).onUpdate((e) => {
|
|
2023
|
+
ghostSize.value = (vertical ? e.y : e.x) - ghostStart.value;
|
|
2024
|
+
}).onEnd((e, success) => {
|
|
2025
|
+
ghostVisible.value = 0;
|
|
2026
|
+
if (success) (0, react_native_reanimated.runOnJS)(commitCreate)(ghostStart.value, vertical ? e.y : e.x);
|
|
2027
|
+
}).onFinalize(() => {
|
|
2028
|
+
ghostVisible.value = 0;
|
|
2029
|
+
}) : null;
|
|
2030
|
+
const activatedPan = pan ? isWeb ? vertical ? pan.activeOffsetY([-8, DRAG_ACTIVATE_PX]) : pan.activeOffsetX([-8, DRAG_ACTIVATE_PX]) : pan.activateAfterLongPress(MOVE_ACTIVATE_MS) : null;
|
|
2031
|
+
const tap = isWeb && onPressCell ? react_native_gesture_handler.Gesture.Tap().onEnd((e) => {
|
|
2032
|
+
(0, react_native_reanimated.runOnJS)(pressAt)(vertical ? e.y : e.x);
|
|
2033
|
+
}) : null;
|
|
2034
|
+
if (activatedPan && tap) return react_native_gesture_handler.Gesture.Exclusive(activatedPan, tap);
|
|
2035
|
+
return activatedPan ?? tap;
|
|
2036
|
+
}, [
|
|
2037
|
+
onCreateEvent,
|
|
2038
|
+
onPressCell,
|
|
2039
|
+
vertical,
|
|
2040
|
+
commitCreate,
|
|
2041
|
+
pressAt,
|
|
2042
|
+
ghostStart,
|
|
2043
|
+
ghostSize,
|
|
2044
|
+
ghostVisible
|
|
2045
|
+
]);
|
|
2046
|
+
const ghostStyle = (0, react_native_reanimated.useAnimatedStyle)(() => {
|
|
2047
|
+
const stepPx = snapMinutes / MINUTES_PER_HOUR * hourSize;
|
|
2048
|
+
const snap = (v) => stepPx > 0 ? Math.round(v / stepPx) * stepPx : v;
|
|
2049
|
+
const a = snap(ghostStart.value);
|
|
2050
|
+
const b = snap(ghostStart.value + ghostSize.value);
|
|
2051
|
+
const from = Math.min(a, b);
|
|
2052
|
+
const size = Math.max(Math.abs(b - a), 2);
|
|
2053
|
+
return vertical ? {
|
|
2054
|
+
opacity: ghostVisible.value,
|
|
2055
|
+
top: from,
|
|
2056
|
+
height: size
|
|
2057
|
+
} : {
|
|
2058
|
+
opacity: ghostVisible.value,
|
|
2059
|
+
left: from,
|
|
2060
|
+
width: size
|
|
2061
|
+
};
|
|
2062
|
+
}, [
|
|
2063
|
+
vertical,
|
|
2064
|
+
hourSize,
|
|
2065
|
+
snapMinutes
|
|
2066
|
+
]);
|
|
2067
|
+
const pxOf = (e) => vertical ? e.nativeEvent.locationY : e.nativeEvent.locationX;
|
|
2068
|
+
const handlePress = onPressCell ? (e) => pressAt(pxOf(e)) : void 0;
|
|
2069
|
+
const handleLongPress = onLongPressCell && !onCreateEvent ? (e) => {
|
|
2070
|
+
const at = timeAt(pxOf(e));
|
|
2071
|
+
if (at) onLongPressCell(at, resource);
|
|
2072
|
+
} : void 0;
|
|
2073
|
+
const layer = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
|
|
2074
|
+
testID: "resource-cell-layer",
|
|
2075
|
+
style: react_native.StyleSheet.absoluteFill,
|
|
2076
|
+
onPress: handlePress,
|
|
2077
|
+
onLongPress: handleLongPress,
|
|
2078
|
+
accessibilityElementsHidden: true,
|
|
2079
|
+
importantForAccessibility: "no"
|
|
2080
|
+
});
|
|
2081
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [laneGesture ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
|
|
2082
|
+
gesture: laneGesture,
|
|
2083
|
+
children: layer
|
|
2084
|
+
}) : layer, onCreateEvent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
|
|
2085
|
+
testID: "resource-create-ghost",
|
|
2086
|
+
pointerEvents: "none",
|
|
2087
|
+
style: [
|
|
2088
|
+
vertical ? styles.vcreateGhost : styles.hcreateGhost,
|
|
2089
|
+
{
|
|
2090
|
+
backgroundColor: theme.colors.eventBackground,
|
|
2091
|
+
borderColor: theme.colors.todayBackground
|
|
2092
|
+
},
|
|
2093
|
+
ghostStyle
|
|
2094
|
+
]
|
|
2095
|
+
}) : null] });
|
|
2096
|
+
}
|
|
1985
2097
|
/**
|
|
1986
2098
|
* A horizontal resource timeline: rows are resources (rooms, people, machines)
|
|
1987
2099
|
* and the x-axis is one day's hours. Events sit in their resource's row, and
|
|
@@ -2000,9 +2112,11 @@ function ResourceBar({ pe, vertical, hourSize, left, top, width, height, rendere
|
|
|
2000
2112
|
* />
|
|
2001
2113
|
* ```
|
|
2002
2114
|
*/
|
|
2003
|
-
function ResourceTimeline({ date, orientation = "horizontal", resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, hourHeight = 48, rowHeight = 56, labelWidth = 140, ampm = false, renderEvent, onPressEvent, onDragEvent, dragStepMinutes = 15 }) {
|
|
2115
|
+
function ResourceTimeline({ date, orientation = "horizontal", resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, hourHeight = 48, rowHeight = 56, labelWidth = 140, ampm = false, renderEvent, onPressEvent, onLongPressEvent, onDragEvent, onPressCell, onLongPressCell, onCreateEvent, businessHours, dragStepMinutes = 15 }) {
|
|
2004
2116
|
const theme = require_MonthList.useCalendarTheme();
|
|
2005
2117
|
const Renderer = renderEvent ?? DefaultBar;
|
|
2118
|
+
const cellEnabled = !!onPressCell || !!onLongPressCell || !!onCreateEvent;
|
|
2119
|
+
const bandsFor = (resource) => businessHours ? (0, _super_calendar_core.closedHourBands)(date, (d) => businessHours(d, resource), startHour, endHour) : [];
|
|
2006
2120
|
const hours = (0, react.useMemo)(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
|
|
2007
2121
|
const trackWidth = (endHour - startHour) * hourWidth;
|
|
2008
2122
|
const byResource = (0, react.useMemo)(() => {
|
|
@@ -2055,58 +2169,84 @@ function ResourceTimeline({ date, orientation = "horizontal", resources, events,
|
|
|
2055
2169
|
{ borderLeftColor: theme.colors.gridLine },
|
|
2056
2170
|
theme.containers.resourceRow
|
|
2057
2171
|
],
|
|
2058
|
-
children: [
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2172
|
+
children: [
|
|
2173
|
+
bandsFor(resource).map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
2174
|
+
pointerEvents: "none",
|
|
2175
|
+
testID: "resource-hours-shade",
|
|
2176
|
+
style: [styles.vshadeBand, {
|
|
2177
|
+
top: (b.start - startHour) * hourHeight,
|
|
2178
|
+
height: (b.end - b.start) * hourHeight,
|
|
2179
|
+
backgroundColor: theme.colors.outsideHoursBackground
|
|
2180
|
+
}]
|
|
2181
|
+
}, `shade-${b.start}`)),
|
|
2182
|
+
hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
2183
|
+
pointerEvents: "none",
|
|
2184
|
+
style: [styles.vgridLine, {
|
|
2185
|
+
top: (h - startHour) * hourHeight,
|
|
2186
|
+
backgroundColor: theme.colors.gridLine
|
|
2187
|
+
}]
|
|
2188
|
+
}, h)),
|
|
2189
|
+
cellEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LaneInteractionLayer, {
|
|
2190
|
+
resource,
|
|
2074
2191
|
vertical: true,
|
|
2075
2192
|
hourSize: hourHeight,
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
width,
|
|
2079
|
-
height,
|
|
2080
|
-
rendererSize: {
|
|
2081
|
-
width: 0,
|
|
2082
|
-
height
|
|
2083
|
-
},
|
|
2193
|
+
startHour,
|
|
2194
|
+
date,
|
|
2084
2195
|
snapMinutes: dragStepMinutes,
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2196
|
+
onPressCell,
|
|
2197
|
+
onLongPressCell,
|
|
2198
|
+
onCreateEvent,
|
|
2088
2199
|
theme
|
|
2089
|
-
},
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2200
|
+
}) : null,
|
|
2201
|
+
positioned.map((pe, idx) => {
|
|
2202
|
+
const top = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourHeight;
|
|
2203
|
+
const bottomPx = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourHeight;
|
|
2204
|
+
const height = Math.max(bottomPx - top, 2);
|
|
2205
|
+
const lanePct = 100 / pe.columns;
|
|
2206
|
+
const left = `${pe.column * lanePct}%`;
|
|
2207
|
+
const width = `${lanePct}%`;
|
|
2208
|
+
const onPress = () => onPressEvent?.(pe.event);
|
|
2209
|
+
if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
|
|
2210
|
+
pe,
|
|
2211
|
+
vertical: true,
|
|
2212
|
+
hourSize: hourHeight,
|
|
2096
2213
|
left,
|
|
2097
|
-
width,
|
|
2098
2214
|
top,
|
|
2215
|
+
width,
|
|
2099
2216
|
height,
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
onPress
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2217
|
+
rendererSize: {
|
|
2218
|
+
width: 0,
|
|
2219
|
+
height
|
|
2220
|
+
},
|
|
2221
|
+
snapMinutes: dragStepMinutes,
|
|
2222
|
+
Renderer,
|
|
2223
|
+
onPress,
|
|
2224
|
+
onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
|
|
2225
|
+
onDragEvent,
|
|
2226
|
+
theme
|
|
2227
|
+
}, idx);
|
|
2228
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
|
|
2229
|
+
onPress,
|
|
2230
|
+
onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
|
|
2231
|
+
accessibilityRole: "button",
|
|
2232
|
+
accessibilityLabel: pe.event.title,
|
|
2233
|
+
style: {
|
|
2234
|
+
position: "absolute",
|
|
2235
|
+
left,
|
|
2236
|
+
width,
|
|
2237
|
+
top,
|
|
2238
|
+
height,
|
|
2239
|
+
padding: 1
|
|
2240
|
+
},
|
|
2241
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
|
|
2242
|
+
event: pe.event,
|
|
2243
|
+
width: 0,
|
|
2244
|
+
height,
|
|
2245
|
+
onPress
|
|
2246
|
+
})
|
|
2247
|
+
}, idx);
|
|
2248
|
+
})
|
|
2249
|
+
]
|
|
2110
2250
|
}, resource.id);
|
|
2111
2251
|
})]
|
|
2112
2252
|
})
|
|
@@ -2163,52 +2303,78 @@ function ResourceTimeline({ date, orientation = "horizontal", resources, events,
|
|
|
2163
2303
|
})
|
|
2164
2304
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
|
|
2165
2305
|
style: { width: trackWidth },
|
|
2166
|
-
children: [
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2306
|
+
children: [
|
|
2307
|
+
bandsFor(resource).map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
2308
|
+
pointerEvents: "none",
|
|
2309
|
+
testID: "resource-hours-shade",
|
|
2310
|
+
style: [styles.hshadeBand, {
|
|
2311
|
+
left: (b.start - startHour) * hourWidth,
|
|
2312
|
+
width: (b.end - b.start) * hourWidth,
|
|
2313
|
+
backgroundColor: theme.colors.outsideHoursBackground
|
|
2314
|
+
}]
|
|
2315
|
+
}, `shade-${b.start}`)),
|
|
2316
|
+
hours.slice(1).map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
2317
|
+
pointerEvents: "none",
|
|
2318
|
+
style: [styles.gridLine, {
|
|
2319
|
+
left: (h - startHour) * hourWidth,
|
|
2320
|
+
backgroundColor: theme.colors.gridLine
|
|
2321
|
+
}]
|
|
2322
|
+
}, h)),
|
|
2323
|
+
cellEnabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LaneInteractionLayer, {
|
|
2324
|
+
resource,
|
|
2180
2325
|
vertical: false,
|
|
2181
2326
|
hourSize: hourWidth,
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
width,
|
|
2185
|
-
height: laneHeight,
|
|
2186
|
-
rendererSize: { width },
|
|
2327
|
+
startHour,
|
|
2328
|
+
date,
|
|
2187
2329
|
snapMinutes: dragStepMinutes,
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2330
|
+
onPressCell,
|
|
2331
|
+
onLongPressCell,
|
|
2332
|
+
onCreateEvent,
|
|
2191
2333
|
theme
|
|
2192
|
-
},
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2334
|
+
}) : null,
|
|
2335
|
+
positioned.map((pe, idx) => {
|
|
2336
|
+
const left = clamp(pe.startHours - startHour, 0, endHour - startHour) * hourWidth;
|
|
2337
|
+
const right = clamp(pe.startHours + pe.durationHours - startHour, 0, endHour - startHour) * hourWidth;
|
|
2338
|
+
const width = Math.max(right - left, 2);
|
|
2339
|
+
const laneHeight = rowHeight / pe.columns;
|
|
2340
|
+
const onPress = () => onPressEvent?.(pe.event);
|
|
2341
|
+
if (onDragEvent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceBar, {
|
|
2342
|
+
pe,
|
|
2343
|
+
vertical: false,
|
|
2344
|
+
hourSize: hourWidth,
|
|
2199
2345
|
left,
|
|
2200
|
-
width,
|
|
2201
2346
|
top: pe.column * laneHeight,
|
|
2202
|
-
height: laneHeight,
|
|
2203
|
-
padding: 1
|
|
2204
|
-
},
|
|
2205
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
|
|
2206
|
-
event: pe.event,
|
|
2207
2347
|
width,
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2348
|
+
height: laneHeight,
|
|
2349
|
+
rendererSize: { width },
|
|
2350
|
+
snapMinutes: dragStepMinutes,
|
|
2351
|
+
Renderer,
|
|
2352
|
+
onPress,
|
|
2353
|
+
onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
|
|
2354
|
+
onDragEvent,
|
|
2355
|
+
theme
|
|
2356
|
+
}, idx);
|
|
2357
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
|
|
2358
|
+
onPress,
|
|
2359
|
+
onLongPress: onLongPressEvent ? () => onLongPressEvent(pe.event) : void 0,
|
|
2360
|
+
accessibilityRole: "button",
|
|
2361
|
+
accessibilityLabel: pe.event.title,
|
|
2362
|
+
style: {
|
|
2363
|
+
position: "absolute",
|
|
2364
|
+
left,
|
|
2365
|
+
width,
|
|
2366
|
+
top: pe.column * laneHeight,
|
|
2367
|
+
height: laneHeight,
|
|
2368
|
+
padding: 1
|
|
2369
|
+
},
|
|
2370
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, {
|
|
2371
|
+
event: pe.event,
|
|
2372
|
+
width,
|
|
2373
|
+
onPress
|
|
2374
|
+
})
|
|
2375
|
+
}, idx);
|
|
2376
|
+
})
|
|
2377
|
+
]
|
|
2212
2378
|
})]
|
|
2213
2379
|
}, resource.id);
|
|
2214
2380
|
})]
|
|
@@ -2298,6 +2464,34 @@ const styles = react_native.StyleSheet.create({
|
|
|
2298
2464
|
left: 0,
|
|
2299
2465
|
right: 0,
|
|
2300
2466
|
height: react_native.StyleSheet.hairlineWidth
|
|
2467
|
+
},
|
|
2468
|
+
vcreateGhost: {
|
|
2469
|
+
position: "absolute",
|
|
2470
|
+
left: 2,
|
|
2471
|
+
right: 2,
|
|
2472
|
+
borderWidth: 1,
|
|
2473
|
+
borderRadius: 6,
|
|
2474
|
+
opacity: 0,
|
|
2475
|
+
zIndex: 2
|
|
2476
|
+
},
|
|
2477
|
+
hcreateGhost: {
|
|
2478
|
+
position: "absolute",
|
|
2479
|
+
top: 2,
|
|
2480
|
+
bottom: 2,
|
|
2481
|
+
borderWidth: 1,
|
|
2482
|
+
borderRadius: 6,
|
|
2483
|
+
opacity: 0,
|
|
2484
|
+
zIndex: 2
|
|
2485
|
+
},
|
|
2486
|
+
hshadeBand: {
|
|
2487
|
+
position: "absolute",
|
|
2488
|
+
top: 0,
|
|
2489
|
+
bottom: 0
|
|
2490
|
+
},
|
|
2491
|
+
vshadeBand: {
|
|
2492
|
+
position: "absolute",
|
|
2493
|
+
left: 0,
|
|
2494
|
+
right: 0
|
|
2301
2495
|
}
|
|
2302
2496
|
});
|
|
2303
2497
|
//#endregion
|