@sunsama/event-calendar 0.2.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/LICENSE +20 -0
- package/README.md +105 -0
- package/lib/commonjs/components/all-day-events.js +117 -0
- package/lib/commonjs/components/all-day-events.js.map +1 -0
- package/lib/commonjs/components/background-hours-content.js +43 -0
- package/lib/commonjs/components/background-hours-content.js.map +1 -0
- package/lib/commonjs/components/background-hours-layout.js +57 -0
- package/lib/commonjs/components/background-hours-layout.js.map +1 -0
- package/lib/commonjs/components/drag-bar.js +84 -0
- package/lib/commonjs/components/drag-bar.js.map +1 -0
- package/lib/commonjs/components/edit-event-container.js +114 -0
- package/lib/commonjs/components/edit-event-container.js.map +1 -0
- package/lib/commonjs/components/event-container.js +37 -0
- package/lib/commonjs/components/event-container.js.map +1 -0
- package/lib/commonjs/components/new-event-container.js +73 -0
- package/lib/commonjs/components/new-event-container.js.map +1 -0
- package/lib/commonjs/components/time-indicator.js +64 -0
- package/lib/commonjs/components/time-indicator.js.map +1 -0
- package/lib/commonjs/components/timed-event-container.js +91 -0
- package/lib/commonjs/components/timed-event-container.js.map +1 -0
- package/lib/commonjs/components/timed-events.js +68 -0
- package/lib/commonjs/components/timed-events.js.map +1 -0
- package/lib/commonjs/components/zoom-provider.js +109 -0
- package/lib/commonjs/components/zoom-provider.js.map +1 -0
- package/lib/commonjs/enums.js +2 -0
- package/lib/commonjs/enums.js.map +1 -0
- package/lib/commonjs/hooks/use-cloned-events.js +25 -0
- package/lib/commonjs/hooks/use-cloned-events.js.map +1 -0
- package/lib/commonjs/hooks/use-events-layout.js +34 -0
- package/lib/commonjs/hooks/use-events-layout.js.map +1 -0
- package/lib/commonjs/hooks/use-is-editing.js +83 -0
- package/lib/commonjs/hooks/use-is-editing.js.map +1 -0
- package/lib/commonjs/index.js +129 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +24 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/calendar-layout.js +113 -0
- package/lib/commonjs/utils/calendar-layout.js.map +1 -0
- package/lib/commonjs/utils/compute-positioning.js +33 -0
- package/lib/commonjs/utils/compute-positioning.js.map +1 -0
- package/lib/commonjs/utils/date-utils.js +152 -0
- package/lib/commonjs/utils/date-utils.js.map +1 -0
- package/lib/commonjs/utils/double-tap-reset-zoom-gesture.js +19 -0
- package/lib/commonjs/utils/double-tap-reset-zoom-gesture.js.map +1 -0
- package/lib/commonjs/utils/generate-event-layouts.js +198 -0
- package/lib/commonjs/utils/generate-event-layouts.js.map +1 -0
- package/lib/commonjs/utils/globals.js +11 -0
- package/lib/commonjs/utils/globals.js.map +1 -0
- package/lib/commonjs/utils/pan-edit-event-gesture.js +41 -0
- package/lib/commonjs/utils/pan-edit-event-gesture.js.map +1 -0
- package/lib/module/components/all-day-events.js +110 -0
- package/lib/module/components/all-day-events.js.map +1 -0
- package/lib/module/components/background-hours-content.js +37 -0
- package/lib/module/components/background-hours-content.js.map +1 -0
- package/lib/module/components/background-hours-layout.js +51 -0
- package/lib/module/components/background-hours-layout.js.map +1 -0
- package/lib/module/components/drag-bar.js +78 -0
- package/lib/module/components/drag-bar.js.map +1 -0
- package/lib/module/components/edit-event-container.js +107 -0
- package/lib/module/components/edit-event-container.js.map +1 -0
- package/lib/module/components/event-container.js +33 -0
- package/lib/module/components/event-container.js.map +1 -0
- package/lib/module/components/new-event-container.js +67 -0
- package/lib/module/components/new-event-container.js.map +1 -0
- package/lib/module/components/time-indicator.js +57 -0
- package/lib/module/components/time-indicator.js.map +1 -0
- package/lib/module/components/timed-event-container.js +84 -0
- package/lib/module/components/timed-event-container.js.map +1 -0
- package/lib/module/components/timed-events.js +63 -0
- package/lib/module/components/timed-events.js.map +1 -0
- package/lib/module/components/zoom-provider.js +102 -0
- package/lib/module/components/zoom-provider.js.map +1 -0
- package/lib/module/enums.js +2 -0
- package/lib/module/enums.js.map +1 -0
- package/lib/module/hooks/use-cloned-events.js +21 -0
- package/lib/module/hooks/use-cloned-events.js.map +1 -0
- package/lib/module/hooks/use-events-layout.js +29 -0
- package/lib/module/hooks/use-events-layout.js.map +1 -0
- package/lib/module/hooks/use-is-editing.js +75 -0
- package/lib/module/hooks/use-is-editing.js.map +1 -0
- package/lib/module/index.js +124 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +20 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/calendar-layout.js +108 -0
- package/lib/module/utils/calendar-layout.js.map +1 -0
- package/lib/module/utils/compute-positioning.js +28 -0
- package/lib/module/utils/compute-positioning.js.map +1 -0
- package/lib/module/utils/date-utils.js +139 -0
- package/lib/module/utils/date-utils.js.map +1 -0
- package/lib/module/utils/double-tap-reset-zoom-gesture.js +15 -0
- package/lib/module/utils/double-tap-reset-zoom-gesture.js.map +1 -0
- package/lib/module/utils/generate-event-layouts.js +192 -0
- package/lib/module/utils/generate-event-layouts.js.map +1 -0
- package/lib/module/utils/globals.js +7 -0
- package/lib/module/utils/globals.js.map +1 -0
- package/lib/module/utils/pan-edit-event-gesture.js +37 -0
- package/lib/module/utils/pan-edit-event-gesture.js.map +1 -0
- package/lib/typescript/commonjs/components/all-day-events.d.ts +3 -0
- package/lib/typescript/commonjs/components/all-day-events.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/background-hours-content.d.ts +7 -0
- package/lib/typescript/commonjs/components/background-hours-content.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/background-hours-layout.d.ts +7 -0
- package/lib/typescript/commonjs/components/background-hours-layout.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/drag-bar.d.ts +14 -0
- package/lib/typescript/commonjs/components/drag-bar.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/edit-event-container.d.ts +7 -0
- package/lib/typescript/commonjs/components/edit-event-container.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/event-container.d.ts +7 -0
- package/lib/typescript/commonjs/components/event-container.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/new-event-container.d.ts +3 -0
- package/lib/typescript/commonjs/components/new-event-container.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/time-indicator.d.ts +3 -0
- package/lib/typescript/commonjs/components/time-indicator.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/timed-event-container.d.ts +9 -0
- package/lib/typescript/commonjs/components/timed-event-container.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/timed-events.d.ts +7 -0
- package/lib/typescript/commonjs/components/timed-events.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/zoom-provider.d.ts +7 -0
- package/lib/typescript/commonjs/components/zoom-provider.d.ts.map +1 -0
- package/lib/typescript/commonjs/enums.d.ts +2 -0
- package/lib/typescript/commonjs/enums.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/use-cloned-events.d.ts +11 -0
- package/lib/typescript/commonjs/hooks/use-cloned-events.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/use-events-layout.d.ts +13 -0
- package/lib/typescript/commonjs/hooks/use-events-layout.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/use-is-editing.d.ts +17 -0
- package/lib/typescript/commonjs/hooks/use-is-editing.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +27 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/types.d.ts +128 -0
- package/lib/typescript/commonjs/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/__tests___/compute-positioning.test.d.ts +2 -0
- package/lib/typescript/commonjs/utils/__tests___/compute-positioning.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/__tests___/date-utils.test.d.ts +2 -0
- package/lib/typescript/commonjs/utils/__tests___/date-utils.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/__tests___/generate-event-layout.test.d.ts +2 -0
- package/lib/typescript/commonjs/utils/__tests___/generate-event-layout.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/calendar-layout.d.ts +36 -0
- package/lib/typescript/commonjs/utils/calendar-layout.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/compute-positioning.d.ts +10 -0
- package/lib/typescript/commonjs/utils/compute-positioning.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/date-utils.d.ts +30 -0
- package/lib/typescript/commonjs/utils/date-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/double-tap-reset-zoom-gesture.d.ts +5 -0
- package/lib/typescript/commonjs/utils/double-tap-reset-zoom-gesture.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/generate-event-layouts.d.ts +15 -0
- package/lib/typescript/commonjs/utils/generate-event-layouts.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/globals.d.ts +5 -0
- package/lib/typescript/commonjs/utils/globals.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/pan-edit-event-gesture.d.ts +6 -0
- package/lib/typescript/commonjs/utils/pan-edit-event-gesture.d.ts.map +1 -0
- package/lib/typescript/module/components/all-day-events.d.ts +3 -0
- package/lib/typescript/module/components/all-day-events.d.ts.map +1 -0
- package/lib/typescript/module/components/background-hours-content.d.ts +7 -0
- package/lib/typescript/module/components/background-hours-content.d.ts.map +1 -0
- package/lib/typescript/module/components/background-hours-layout.d.ts +7 -0
- package/lib/typescript/module/components/background-hours-layout.d.ts.map +1 -0
- package/lib/typescript/module/components/drag-bar.d.ts +14 -0
- package/lib/typescript/module/components/drag-bar.d.ts.map +1 -0
- package/lib/typescript/module/components/edit-event-container.d.ts +7 -0
- package/lib/typescript/module/components/edit-event-container.d.ts.map +1 -0
- package/lib/typescript/module/components/event-container.d.ts +7 -0
- package/lib/typescript/module/components/event-container.d.ts.map +1 -0
- package/lib/typescript/module/components/new-event-container.d.ts +3 -0
- package/lib/typescript/module/components/new-event-container.d.ts.map +1 -0
- package/lib/typescript/module/components/time-indicator.d.ts +3 -0
- package/lib/typescript/module/components/time-indicator.d.ts.map +1 -0
- package/lib/typescript/module/components/timed-event-container.d.ts +9 -0
- package/lib/typescript/module/components/timed-event-container.d.ts.map +1 -0
- package/lib/typescript/module/components/timed-events.d.ts +7 -0
- package/lib/typescript/module/components/timed-events.d.ts.map +1 -0
- package/lib/typescript/module/components/zoom-provider.d.ts +7 -0
- package/lib/typescript/module/components/zoom-provider.d.ts.map +1 -0
- package/lib/typescript/module/enums.d.ts +2 -0
- package/lib/typescript/module/enums.d.ts.map +1 -0
- package/lib/typescript/module/hooks/use-cloned-events.d.ts +11 -0
- package/lib/typescript/module/hooks/use-cloned-events.d.ts.map +1 -0
- package/lib/typescript/module/hooks/use-events-layout.d.ts +13 -0
- package/lib/typescript/module/hooks/use-events-layout.d.ts.map +1 -0
- package/lib/typescript/module/hooks/use-is-editing.d.ts +17 -0
- package/lib/typescript/module/hooks/use-is-editing.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +27 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/types.d.ts +128 -0
- package/lib/typescript/module/types.d.ts.map +1 -0
- package/lib/typescript/module/utils/__tests___/compute-positioning.test.d.ts +2 -0
- package/lib/typescript/module/utils/__tests___/compute-positioning.test.d.ts.map +1 -0
- package/lib/typescript/module/utils/__tests___/date-utils.test.d.ts +2 -0
- package/lib/typescript/module/utils/__tests___/date-utils.test.d.ts.map +1 -0
- package/lib/typescript/module/utils/__tests___/generate-event-layout.test.d.ts +2 -0
- package/lib/typescript/module/utils/__tests___/generate-event-layout.test.d.ts.map +1 -0
- package/lib/typescript/module/utils/calendar-layout.d.ts +36 -0
- package/lib/typescript/module/utils/calendar-layout.d.ts.map +1 -0
- package/lib/typescript/module/utils/compute-positioning.d.ts +10 -0
- package/lib/typescript/module/utils/compute-positioning.d.ts.map +1 -0
- package/lib/typescript/module/utils/date-utils.d.ts +30 -0
- package/lib/typescript/module/utils/date-utils.d.ts.map +1 -0
- package/lib/typescript/module/utils/double-tap-reset-zoom-gesture.d.ts +5 -0
- package/lib/typescript/module/utils/double-tap-reset-zoom-gesture.d.ts.map +1 -0
- package/lib/typescript/module/utils/generate-event-layouts.d.ts +15 -0
- package/lib/typescript/module/utils/generate-event-layouts.d.ts.map +1 -0
- package/lib/typescript/module/utils/globals.d.ts +5 -0
- package/lib/typescript/module/utils/globals.d.ts.map +1 -0
- package/lib/typescript/module/utils/pan-edit-event-gesture.d.ts +6 -0
- package/lib/typescript/module/utils/pan-edit-event-gesture.d.ts.map +1 -0
- package/package.json +195 -0
- package/src/components/all-day-events.tsx +134 -0
- package/src/components/background-hours-content.tsx +51 -0
- package/src/components/background-hours-layout.tsx +61 -0
- package/src/components/drag-bar.tsx +120 -0
- package/src/components/edit-event-container.tsx +158 -0
- package/src/components/event-container.tsx +44 -0
- package/src/components/new-event-container.tsx +90 -0
- package/src/components/time-indicator.tsx +72 -0
- package/src/components/timed-event-container.tsx +124 -0
- package/src/components/timed-events.tsx +72 -0
- package/src/components/zoom-provider.tsx +146 -0
- package/src/enums.ts +0 -0
- package/src/hooks/use-cloned-events.ts +26 -0
- package/src/hooks/use-events-layout.ts +55 -0
- package/src/hooks/use-is-editing.tsx +109 -0
- package/src/index.tsx +165 -0
- package/src/types.ts +163 -0
- package/src/utils/__tests___/compute-positioning.test.ts +255 -0
- package/src/utils/__tests___/date-utils.test.ts +41 -0
- package/src/utils/__tests___/generate-event-layout.test.ts +277 -0
- package/src/utils/calendar-layout.ts +139 -0
- package/src/utils/compute-positioning.ts +44 -0
- package/src/utils/date-utils.ts +238 -0
- package/src/utils/double-tap-reset-zoom-gesture.ts +23 -0
- package/src/utils/generate-event-layouts.ts +314 -0
- package/src/utils/globals.ts +8 -0
- package/src/utils/pan-edit-event-gesture.ts +64 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Gesture } from "react-native-gesture-handler";
|
|
2
|
+
import { runOnJS, SharedValue } from "react-native-reanimated";
|
|
3
|
+
import { Config } from "src/types";
|
|
4
|
+
|
|
5
|
+
const doubleTapGesture = (
|
|
6
|
+
zoomLevel: SharedValue<number>,
|
|
7
|
+
initialZoomLevel: number,
|
|
8
|
+
onZoomChange?: Config["onZoomChange"]
|
|
9
|
+
) =>
|
|
10
|
+
Gesture.Tap()
|
|
11
|
+
.numberOfTaps(2)
|
|
12
|
+
.onEnd((_event, success) => {
|
|
13
|
+
if (success) {
|
|
14
|
+
// Reset the zoom level to the default
|
|
15
|
+
zoomLevel.value = initialZoomLevel;
|
|
16
|
+
|
|
17
|
+
if (onZoomChange) {
|
|
18
|
+
runOnJS(onZoomChange)(initialZoomLevel);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default doubleTapGesture;
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import _partition from "lodash/partition";
|
|
2
|
+
import _reduce from "lodash/reduce";
|
|
3
|
+
import _sortBy from "lodash/sortBy";
|
|
4
|
+
import _reverse from "lodash/reverse";
|
|
5
|
+
import moment, { Moment } from "moment-timezone";
|
|
6
|
+
import { CalendarLayout } from "src/utils/calendar-layout";
|
|
7
|
+
import {
|
|
8
|
+
computeCalendarDateRange,
|
|
9
|
+
dateRangeIntersect,
|
|
10
|
+
getDuration,
|
|
11
|
+
getDurationInDays,
|
|
12
|
+
isAllDayOrSpansMidnight,
|
|
13
|
+
startOfUserWeek,
|
|
14
|
+
} from "src/utils/date-utils";
|
|
15
|
+
import computePositioning from "src/utils/compute-positioning";
|
|
16
|
+
import {
|
|
17
|
+
AllDayEventLayoutType,
|
|
18
|
+
CalendarEvent,
|
|
19
|
+
CalendarViewIntervalType,
|
|
20
|
+
CollisionObject,
|
|
21
|
+
EventExtend,
|
|
22
|
+
FullCalendarEventLayout,
|
|
23
|
+
PartDayEventLayoutType,
|
|
24
|
+
} from "src/types";
|
|
25
|
+
|
|
26
|
+
interface GenerateEventLayouts {
|
|
27
|
+
events: CalendarEvent[];
|
|
28
|
+
userCalendarId: string;
|
|
29
|
+
timezone: string;
|
|
30
|
+
startCalendarDate: string;
|
|
31
|
+
endCalendarDate: string;
|
|
32
|
+
startDayOfWeekOffset?: number;
|
|
33
|
+
calendarViewInterval?: CalendarViewIntervalType;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const generateEventLayouts = ({
|
|
37
|
+
events,
|
|
38
|
+
startCalendarDate,
|
|
39
|
+
endCalendarDate,
|
|
40
|
+
userCalendarId,
|
|
41
|
+
calendarViewInterval = "1day",
|
|
42
|
+
startDayOfWeekOffset = 0,
|
|
43
|
+
timezone,
|
|
44
|
+
}: GenerateEventLayouts) => {
|
|
45
|
+
// Calculate spacial layout for CalendarViewDay events
|
|
46
|
+
// in month view, midnight-spanning part-day events are rendered as all-day multi-day
|
|
47
|
+
const [allDayEvents, partDayEvents] = _partition([...events], (event) =>
|
|
48
|
+
isAllDayOrSpansMidnight(event, timezone)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// lowest priority sort by ID for consistent ordering of otherwise equal events
|
|
52
|
+
let allDayEventsSorted = _sortBy(allDayEvents, (event) => event.id);
|
|
53
|
+
|
|
54
|
+
// secondary sort by length descending
|
|
55
|
+
allDayEventsSorted = _sortBy(allDayEventsSorted, (event) =>
|
|
56
|
+
getDurationInDays(event, timezone)
|
|
57
|
+
);
|
|
58
|
+
allDayEventsSorted = _reverse(allDayEventsSorted);
|
|
59
|
+
|
|
60
|
+
// primary sort by start ascending
|
|
61
|
+
allDayEventsSorted = _sortBy(allDayEventsSorted, (event) =>
|
|
62
|
+
new Date(event.start).valueOf()
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// lowest priority sort by ID for consistent ordering of otherwise equal events
|
|
66
|
+
let partDayEventsSorted = _sortBy(partDayEvents, (event) => event.id);
|
|
67
|
+
|
|
68
|
+
partDayEventsSorted = _sortBy(partDayEventsSorted, (event) =>
|
|
69
|
+
getDuration(event)
|
|
70
|
+
); // secondary sort by duration ascending
|
|
71
|
+
partDayEventsSorted = _sortBy(partDayEventsSorted, (event) =>
|
|
72
|
+
new Date(event.start).valueOf()
|
|
73
|
+
); // primary sort by start ascending
|
|
74
|
+
const calendarViewDayEvents = [
|
|
75
|
+
...allDayEventsSorted,
|
|
76
|
+
...(calendarViewInterval === "month" ? partDayEventsSorted : []),
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const visibleDayCount = moment
|
|
80
|
+
.tz(endCalendarDate, timezone)
|
|
81
|
+
.diff(moment.tz(startCalendarDate, timezone), "days");
|
|
82
|
+
const visibleDays: string[] = [];
|
|
83
|
+
for (let dayCount = 0; dayCount <= visibleDayCount; dayCount++) {
|
|
84
|
+
visibleDays.push(
|
|
85
|
+
moment
|
|
86
|
+
.tz(startCalendarDate, timezone)
|
|
87
|
+
.add(dayCount, "day")
|
|
88
|
+
.format("YYYY-MM-DD")
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const calendarViewDateRanges = visibleDays.map((visibleDay) => {
|
|
93
|
+
return computeCalendarDateRange(
|
|
94
|
+
visibleDay,
|
|
95
|
+
timezone,
|
|
96
|
+
calendarViewInterval,
|
|
97
|
+
startDayOfWeekOffset
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const result: {
|
|
102
|
+
[day: string]: FullCalendarEventLayout;
|
|
103
|
+
} = {};
|
|
104
|
+
|
|
105
|
+
calendarViewDateRanges.forEach((date) => {
|
|
106
|
+
const calendarLayoutOptions = {
|
|
107
|
+
visibleX: date.dayIndexes,
|
|
108
|
+
enableWeekBreaks: calendarViewInterval === "month",
|
|
109
|
+
startOfWeekXOffset: moment
|
|
110
|
+
.tz(date.basisDate, timezone)
|
|
111
|
+
.diff(
|
|
112
|
+
startOfUserWeek(startDayOfWeekOffset, date.basisDate!, timezone),
|
|
113
|
+
"days"
|
|
114
|
+
),
|
|
115
|
+
};
|
|
116
|
+
const calendarViewDayLayout = _reduce(
|
|
117
|
+
calendarViewDayEvents,
|
|
118
|
+
(calendarLayout, event) => {
|
|
119
|
+
const eventStartIndex = moment
|
|
120
|
+
.tz(event.start, timezone)
|
|
121
|
+
.startOf("day")
|
|
122
|
+
.diff(moment.tz(date.basisDate, timezone), "days");
|
|
123
|
+
const eventDurationDays = getDurationInDays(event, timezone);
|
|
124
|
+
|
|
125
|
+
calendarLayout.findFitAndInsert(
|
|
126
|
+
eventStartIndex,
|
|
127
|
+
eventDurationDays,
|
|
128
|
+
event
|
|
129
|
+
);
|
|
130
|
+
return calendarLayout;
|
|
131
|
+
},
|
|
132
|
+
new CalendarLayout(calendarLayoutOptions)
|
|
133
|
+
);
|
|
134
|
+
const calendarViewDayRowHeight = calendarViewDayLayout.height();
|
|
135
|
+
|
|
136
|
+
// set the calendar layout for each day
|
|
137
|
+
const calendarDates = date.calendarDates || [];
|
|
138
|
+
|
|
139
|
+
calendarDates.forEach((calendarDate) => {
|
|
140
|
+
const currentDayDate = moment.tz(calendarDate, timezone).startOf("day");
|
|
141
|
+
const startDate = currentDayDate.toDate();
|
|
142
|
+
const endDate = moment.tz(startDate, timezone).endOf("day").toDate();
|
|
143
|
+
const showHours = !["month"].includes(calendarViewInterval);
|
|
144
|
+
const dayId = calendarDate;
|
|
145
|
+
const allDayEventsLayout: AllDayEventLayoutType[] = [];
|
|
146
|
+
let partDayEventsLayout: PartDayEventLayoutType[] = [];
|
|
147
|
+
|
|
148
|
+
const x = moment(startDate).diff(
|
|
149
|
+
moment.tz(date.basisDate, timezone),
|
|
150
|
+
"days"
|
|
151
|
+
);
|
|
152
|
+
for (let y = 0; y < calendarViewDayRowHeight; ++y) {
|
|
153
|
+
const {
|
|
154
|
+
event,
|
|
155
|
+
visibleWidthDays,
|
|
156
|
+
extend = EventExtend.None,
|
|
157
|
+
isPrimaryRendered,
|
|
158
|
+
} = calendarViewDayLayout.getViewAt(x, y);
|
|
159
|
+
if (event) {
|
|
160
|
+
allDayEventsLayout.push({
|
|
161
|
+
event,
|
|
162
|
+
rowIndex: y,
|
|
163
|
+
// @ts-ignore we know visibleWidthDays will be set for all day events if an event is returned
|
|
164
|
+
visibleWidthDays,
|
|
165
|
+
extend,
|
|
166
|
+
isPrimaryRendered,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Handle part day events according to view type
|
|
172
|
+
if (showHours) {
|
|
173
|
+
// Bucket, partition, sort, and handle collisions
|
|
174
|
+
partDayEventsLayout = partDayEventsLayout.concat(
|
|
175
|
+
handleCollisions(
|
|
176
|
+
events.filter(
|
|
177
|
+
(event) =>
|
|
178
|
+
!isAllDayOrSpansMidnight(event, timezone) &&
|
|
179
|
+
dateRangeIntersect(
|
|
180
|
+
{
|
|
181
|
+
startDate: new Date(event.start),
|
|
182
|
+
endDate: new Date(event.end),
|
|
183
|
+
},
|
|
184
|
+
{ startDate, endDate }
|
|
185
|
+
)
|
|
186
|
+
),
|
|
187
|
+
userCalendarId,
|
|
188
|
+
currentDayDate,
|
|
189
|
+
timezone
|
|
190
|
+
)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
result[dayId] = {
|
|
195
|
+
allDayEventsLayout,
|
|
196
|
+
partDayEventsLayout,
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
return result;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const combineEventPosition = (
|
|
205
|
+
dayDate: Moment,
|
|
206
|
+
timezone: string,
|
|
207
|
+
collisionObject: CollisionObject
|
|
208
|
+
): PartDayEventLayoutType => {
|
|
209
|
+
const position = computePositioning({
|
|
210
|
+
timezone,
|
|
211
|
+
collisionObject: collisionObject,
|
|
212
|
+
startOfDayMoment: dayDate,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
...collisionObject,
|
|
217
|
+
position,
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const handleCollisions = (
|
|
222
|
+
allEvents: CalendarEvent[],
|
|
223
|
+
userCalendarId: string,
|
|
224
|
+
dayDate: Moment,
|
|
225
|
+
timezone: string
|
|
226
|
+
): PartDayEventLayoutType[] => {
|
|
227
|
+
let stackableEvents = _sortBy(allEvents, (event) => event.id);
|
|
228
|
+
stackableEvents = _sortBy(stackableEvents, (event) => {
|
|
229
|
+
// current user's primary calendar should always be leftmost option
|
|
230
|
+
return event.calendarId && !event.calendarId.includes(userCalendarId);
|
|
231
|
+
});
|
|
232
|
+
stackableEvents = _sortBy(stackableEvents, (event) =>
|
|
233
|
+
new Date(event.start).valueOf()
|
|
234
|
+
);
|
|
235
|
+
// calculate overlap stack properties
|
|
236
|
+
const stackedEvtsByPos: Record<string, PartDayEventLayoutType[]> = {};
|
|
237
|
+
let curStack: (CollisionObject | null)[] = [];
|
|
238
|
+
|
|
239
|
+
for (const evt of stackableEvents) {
|
|
240
|
+
// already sorted by startDate
|
|
241
|
+
for (let idx = 0; idx < curStack.length; idx++) {
|
|
242
|
+
const stackEvt = curStack[idx];
|
|
243
|
+
|
|
244
|
+
if (stackEvt) {
|
|
245
|
+
const stackEvtEnd = new Date(stackEvt.event.end).valueOf();
|
|
246
|
+
const stackEvtStart = new Date(stackEvt.event.start).valueOf();
|
|
247
|
+
const eventStart = new Date(evt.start).valueOf();
|
|
248
|
+
|
|
249
|
+
// events shorter than 15 minutes behave as if they had 15 minute duration.
|
|
250
|
+
// matches behavior in calendar view, where the shortest 'height' an event is given matches the height of a 15 minute event.
|
|
251
|
+
const duration = (stackEvtEnd - stackEvtStart) / (1000 * 60);
|
|
252
|
+
const endDate =
|
|
253
|
+
duration < 15 ? stackEvtStart + 15 * 60 * 1000 : stackEvtEnd;
|
|
254
|
+
|
|
255
|
+
if (endDate <= eventStart) {
|
|
256
|
+
// null out this event's position in stack
|
|
257
|
+
curStack[idx] = null;
|
|
258
|
+
|
|
259
|
+
if (curStack.length > 1) {
|
|
260
|
+
stackEvt.collisions = { total: curStack.length, order: idx };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
stackedEvtsByPos[idx]
|
|
264
|
+
? stackedEvtsByPos[idx].push(
|
|
265
|
+
combineEventPosition(dayDate, timezone, stackEvt)
|
|
266
|
+
)
|
|
267
|
+
: (stackedEvtsByPos[idx] = [
|
|
268
|
+
combineEventPosition(dayDate, timezone, stackEvt),
|
|
269
|
+
]);
|
|
270
|
+
|
|
271
|
+
if (!curStack.some((el) => el)) {
|
|
272
|
+
curStack = [];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// plop evt into first null placeholder we find, or just push if we don't have any.
|
|
279
|
+
const spliceIdx = curStack.findIndex((stackEvt) => !stackEvt);
|
|
280
|
+
spliceIdx > -1
|
|
281
|
+
? curStack.splice(spliceIdx, 1, { event: evt })
|
|
282
|
+
: curStack.splice(curStack.length, 0, { event: evt });
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// clean up stack if we've exhausted allEvents and it's unpopped.
|
|
286
|
+
for (let idx = 0; idx < curStack.length; idx++) {
|
|
287
|
+
const stackEvt = curStack[idx];
|
|
288
|
+
|
|
289
|
+
if (stackEvt) {
|
|
290
|
+
if (curStack.length > 1) {
|
|
291
|
+
stackEvt.collisions = { total: curStack.length, order: idx };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
stackedEvtsByPos[idx]
|
|
295
|
+
? stackedEvtsByPos[idx].push(
|
|
296
|
+
combineEventPosition(dayDate, timezone, stackEvt)
|
|
297
|
+
)
|
|
298
|
+
: (stackedEvtsByPos[idx] = [
|
|
299
|
+
combineEventPosition(dayDate, timezone, stackEvt),
|
|
300
|
+
]);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// always draw position 0 stack elements first.
|
|
305
|
+
let stackedEvents: PartDayEventLayoutType[] = [];
|
|
306
|
+
|
|
307
|
+
Object.keys(stackedEvtsByPos).forEach(
|
|
308
|
+
(pos) => (stackedEvents = stackedEvents.concat(stackedEvtsByPos[pos]))
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
return [...stackedEvents];
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
export default generateEventLayouts;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Gesture } from "react-native-gesture-handler";
|
|
2
|
+
import { runOnJS, SharedValue } from "react-native-reanimated";
|
|
3
|
+
import { RefObject } from "react";
|
|
4
|
+
import { PartDayEventLayoutType } from "src/types";
|
|
5
|
+
|
|
6
|
+
const gesturePan = (
|
|
7
|
+
startY: SharedValue<number>,
|
|
8
|
+
top: SharedValue<number>,
|
|
9
|
+
currentY: SharedValue<number>,
|
|
10
|
+
zoomLevel: SharedValue<number>,
|
|
11
|
+
maximumHour: SharedValue<number>,
|
|
12
|
+
height: SharedValue<number>,
|
|
13
|
+
refNewEvent: RefObject<any>,
|
|
14
|
+
fiveMinuteInterval?: boolean,
|
|
15
|
+
isEditing?: null | PartDayEventLayoutType,
|
|
16
|
+
startEditing?: () => void
|
|
17
|
+
) =>
|
|
18
|
+
Gesture.Pan()
|
|
19
|
+
.blocksExternalGesture(refNewEvent)
|
|
20
|
+
.onStart(() => {
|
|
21
|
+
if (startEditing) {
|
|
22
|
+
if (isEditing) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!isEditing) {
|
|
27
|
+
runOnJS(startEditing)();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
startY.value = top.value;
|
|
32
|
+
})
|
|
33
|
+
.onUpdate(({ translationY }) => {
|
|
34
|
+
let freshUpdatedStartTime;
|
|
35
|
+
|
|
36
|
+
if (fiveMinuteInterval) {
|
|
37
|
+
// Set the updated time in 15 minute increments but make sure we never go lower
|
|
38
|
+
// than the first minute of the day
|
|
39
|
+
freshUpdatedStartTime = Math.max(
|
|
40
|
+
0,
|
|
41
|
+
startY.value +
|
|
42
|
+
Math.floor(translationY / zoomLevel.value / 5) *
|
|
43
|
+
(zoomLevel.value * 5)
|
|
44
|
+
);
|
|
45
|
+
} else {
|
|
46
|
+
// Set the updated time in 1 minute increments but make sure we never go lower
|
|
47
|
+
// than the first minute of the day
|
|
48
|
+
freshUpdatedStartTime = Math.max(
|
|
49
|
+
0,
|
|
50
|
+
startY.value +
|
|
51
|
+
Math.floor(translationY / zoomLevel.value) * zoomLevel.value
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Make sure the event does not span after midnight, and if so make sure it
|
|
56
|
+
// is limited to exactly midnight
|
|
57
|
+
if (freshUpdatedStartTime > maximumHour.value - height.value) {
|
|
58
|
+
freshUpdatedStartTime = maximumHour.value - height.value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
currentY.value = freshUpdatedStartTime;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export default gesturePan;
|