@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.
Files changed (236) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +105 -0
  3. package/lib/commonjs/components/all-day-events.js +117 -0
  4. package/lib/commonjs/components/all-day-events.js.map +1 -0
  5. package/lib/commonjs/components/background-hours-content.js +43 -0
  6. package/lib/commonjs/components/background-hours-content.js.map +1 -0
  7. package/lib/commonjs/components/background-hours-layout.js +57 -0
  8. package/lib/commonjs/components/background-hours-layout.js.map +1 -0
  9. package/lib/commonjs/components/drag-bar.js +84 -0
  10. package/lib/commonjs/components/drag-bar.js.map +1 -0
  11. package/lib/commonjs/components/edit-event-container.js +114 -0
  12. package/lib/commonjs/components/edit-event-container.js.map +1 -0
  13. package/lib/commonjs/components/event-container.js +37 -0
  14. package/lib/commonjs/components/event-container.js.map +1 -0
  15. package/lib/commonjs/components/new-event-container.js +73 -0
  16. package/lib/commonjs/components/new-event-container.js.map +1 -0
  17. package/lib/commonjs/components/time-indicator.js +64 -0
  18. package/lib/commonjs/components/time-indicator.js.map +1 -0
  19. package/lib/commonjs/components/timed-event-container.js +91 -0
  20. package/lib/commonjs/components/timed-event-container.js.map +1 -0
  21. package/lib/commonjs/components/timed-events.js +68 -0
  22. package/lib/commonjs/components/timed-events.js.map +1 -0
  23. package/lib/commonjs/components/zoom-provider.js +109 -0
  24. package/lib/commonjs/components/zoom-provider.js.map +1 -0
  25. package/lib/commonjs/enums.js +2 -0
  26. package/lib/commonjs/enums.js.map +1 -0
  27. package/lib/commonjs/hooks/use-cloned-events.js +25 -0
  28. package/lib/commonjs/hooks/use-cloned-events.js.map +1 -0
  29. package/lib/commonjs/hooks/use-events-layout.js +34 -0
  30. package/lib/commonjs/hooks/use-events-layout.js.map +1 -0
  31. package/lib/commonjs/hooks/use-is-editing.js +83 -0
  32. package/lib/commonjs/hooks/use-is-editing.js.map +1 -0
  33. package/lib/commonjs/index.js +129 -0
  34. package/lib/commonjs/index.js.map +1 -0
  35. package/lib/commonjs/types.js +24 -0
  36. package/lib/commonjs/types.js.map +1 -0
  37. package/lib/commonjs/utils/calendar-layout.js +113 -0
  38. package/lib/commonjs/utils/calendar-layout.js.map +1 -0
  39. package/lib/commonjs/utils/compute-positioning.js +33 -0
  40. package/lib/commonjs/utils/compute-positioning.js.map +1 -0
  41. package/lib/commonjs/utils/date-utils.js +152 -0
  42. package/lib/commonjs/utils/date-utils.js.map +1 -0
  43. package/lib/commonjs/utils/double-tap-reset-zoom-gesture.js +19 -0
  44. package/lib/commonjs/utils/double-tap-reset-zoom-gesture.js.map +1 -0
  45. package/lib/commonjs/utils/generate-event-layouts.js +198 -0
  46. package/lib/commonjs/utils/generate-event-layouts.js.map +1 -0
  47. package/lib/commonjs/utils/globals.js +11 -0
  48. package/lib/commonjs/utils/globals.js.map +1 -0
  49. package/lib/commonjs/utils/pan-edit-event-gesture.js +41 -0
  50. package/lib/commonjs/utils/pan-edit-event-gesture.js.map +1 -0
  51. package/lib/module/components/all-day-events.js +110 -0
  52. package/lib/module/components/all-day-events.js.map +1 -0
  53. package/lib/module/components/background-hours-content.js +37 -0
  54. package/lib/module/components/background-hours-content.js.map +1 -0
  55. package/lib/module/components/background-hours-layout.js +51 -0
  56. package/lib/module/components/background-hours-layout.js.map +1 -0
  57. package/lib/module/components/drag-bar.js +78 -0
  58. package/lib/module/components/drag-bar.js.map +1 -0
  59. package/lib/module/components/edit-event-container.js +107 -0
  60. package/lib/module/components/edit-event-container.js.map +1 -0
  61. package/lib/module/components/event-container.js +33 -0
  62. package/lib/module/components/event-container.js.map +1 -0
  63. package/lib/module/components/new-event-container.js +67 -0
  64. package/lib/module/components/new-event-container.js.map +1 -0
  65. package/lib/module/components/time-indicator.js +57 -0
  66. package/lib/module/components/time-indicator.js.map +1 -0
  67. package/lib/module/components/timed-event-container.js +84 -0
  68. package/lib/module/components/timed-event-container.js.map +1 -0
  69. package/lib/module/components/timed-events.js +63 -0
  70. package/lib/module/components/timed-events.js.map +1 -0
  71. package/lib/module/components/zoom-provider.js +102 -0
  72. package/lib/module/components/zoom-provider.js.map +1 -0
  73. package/lib/module/enums.js +2 -0
  74. package/lib/module/enums.js.map +1 -0
  75. package/lib/module/hooks/use-cloned-events.js +21 -0
  76. package/lib/module/hooks/use-cloned-events.js.map +1 -0
  77. package/lib/module/hooks/use-events-layout.js +29 -0
  78. package/lib/module/hooks/use-events-layout.js.map +1 -0
  79. package/lib/module/hooks/use-is-editing.js +75 -0
  80. package/lib/module/hooks/use-is-editing.js.map +1 -0
  81. package/lib/module/index.js +124 -0
  82. package/lib/module/index.js.map +1 -0
  83. package/lib/module/types.js +20 -0
  84. package/lib/module/types.js.map +1 -0
  85. package/lib/module/utils/calendar-layout.js +108 -0
  86. package/lib/module/utils/calendar-layout.js.map +1 -0
  87. package/lib/module/utils/compute-positioning.js +28 -0
  88. package/lib/module/utils/compute-positioning.js.map +1 -0
  89. package/lib/module/utils/date-utils.js +139 -0
  90. package/lib/module/utils/date-utils.js.map +1 -0
  91. package/lib/module/utils/double-tap-reset-zoom-gesture.js +15 -0
  92. package/lib/module/utils/double-tap-reset-zoom-gesture.js.map +1 -0
  93. package/lib/module/utils/generate-event-layouts.js +192 -0
  94. package/lib/module/utils/generate-event-layouts.js.map +1 -0
  95. package/lib/module/utils/globals.js +7 -0
  96. package/lib/module/utils/globals.js.map +1 -0
  97. package/lib/module/utils/pan-edit-event-gesture.js +37 -0
  98. package/lib/module/utils/pan-edit-event-gesture.js.map +1 -0
  99. package/lib/typescript/commonjs/components/all-day-events.d.ts +3 -0
  100. package/lib/typescript/commonjs/components/all-day-events.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/components/background-hours-content.d.ts +7 -0
  102. package/lib/typescript/commonjs/components/background-hours-content.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/components/background-hours-layout.d.ts +7 -0
  104. package/lib/typescript/commonjs/components/background-hours-layout.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/components/drag-bar.d.ts +14 -0
  106. package/lib/typescript/commonjs/components/drag-bar.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/components/edit-event-container.d.ts +7 -0
  108. package/lib/typescript/commonjs/components/edit-event-container.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/components/event-container.d.ts +7 -0
  110. package/lib/typescript/commonjs/components/event-container.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/components/new-event-container.d.ts +3 -0
  112. package/lib/typescript/commonjs/components/new-event-container.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/components/time-indicator.d.ts +3 -0
  114. package/lib/typescript/commonjs/components/time-indicator.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/components/timed-event-container.d.ts +9 -0
  116. package/lib/typescript/commonjs/components/timed-event-container.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/components/timed-events.d.ts +7 -0
  118. package/lib/typescript/commonjs/components/timed-events.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/components/zoom-provider.d.ts +7 -0
  120. package/lib/typescript/commonjs/components/zoom-provider.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/enums.d.ts +2 -0
  122. package/lib/typescript/commonjs/enums.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/hooks/use-cloned-events.d.ts +11 -0
  124. package/lib/typescript/commonjs/hooks/use-cloned-events.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/hooks/use-events-layout.d.ts +13 -0
  126. package/lib/typescript/commonjs/hooks/use-events-layout.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/hooks/use-is-editing.d.ts +17 -0
  128. package/lib/typescript/commonjs/hooks/use-is-editing.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/index.d.ts +27 -0
  130. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/package.json +1 -0
  132. package/lib/typescript/commonjs/types.d.ts +128 -0
  133. package/lib/typescript/commonjs/types.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/utils/__tests___/compute-positioning.test.d.ts +2 -0
  135. package/lib/typescript/commonjs/utils/__tests___/compute-positioning.test.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/utils/__tests___/date-utils.test.d.ts +2 -0
  137. package/lib/typescript/commonjs/utils/__tests___/date-utils.test.d.ts.map +1 -0
  138. package/lib/typescript/commonjs/utils/__tests___/generate-event-layout.test.d.ts +2 -0
  139. package/lib/typescript/commonjs/utils/__tests___/generate-event-layout.test.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/utils/calendar-layout.d.ts +36 -0
  141. package/lib/typescript/commonjs/utils/calendar-layout.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/utils/compute-positioning.d.ts +10 -0
  143. package/lib/typescript/commonjs/utils/compute-positioning.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/utils/date-utils.d.ts +30 -0
  145. package/lib/typescript/commonjs/utils/date-utils.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/utils/double-tap-reset-zoom-gesture.d.ts +5 -0
  147. package/lib/typescript/commonjs/utils/double-tap-reset-zoom-gesture.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/utils/generate-event-layouts.d.ts +15 -0
  149. package/lib/typescript/commonjs/utils/generate-event-layouts.d.ts.map +1 -0
  150. package/lib/typescript/commonjs/utils/globals.d.ts +5 -0
  151. package/lib/typescript/commonjs/utils/globals.d.ts.map +1 -0
  152. package/lib/typescript/commonjs/utils/pan-edit-event-gesture.d.ts +6 -0
  153. package/lib/typescript/commonjs/utils/pan-edit-event-gesture.d.ts.map +1 -0
  154. package/lib/typescript/module/components/all-day-events.d.ts +3 -0
  155. package/lib/typescript/module/components/all-day-events.d.ts.map +1 -0
  156. package/lib/typescript/module/components/background-hours-content.d.ts +7 -0
  157. package/lib/typescript/module/components/background-hours-content.d.ts.map +1 -0
  158. package/lib/typescript/module/components/background-hours-layout.d.ts +7 -0
  159. package/lib/typescript/module/components/background-hours-layout.d.ts.map +1 -0
  160. package/lib/typescript/module/components/drag-bar.d.ts +14 -0
  161. package/lib/typescript/module/components/drag-bar.d.ts.map +1 -0
  162. package/lib/typescript/module/components/edit-event-container.d.ts +7 -0
  163. package/lib/typescript/module/components/edit-event-container.d.ts.map +1 -0
  164. package/lib/typescript/module/components/event-container.d.ts +7 -0
  165. package/lib/typescript/module/components/event-container.d.ts.map +1 -0
  166. package/lib/typescript/module/components/new-event-container.d.ts +3 -0
  167. package/lib/typescript/module/components/new-event-container.d.ts.map +1 -0
  168. package/lib/typescript/module/components/time-indicator.d.ts +3 -0
  169. package/lib/typescript/module/components/time-indicator.d.ts.map +1 -0
  170. package/lib/typescript/module/components/timed-event-container.d.ts +9 -0
  171. package/lib/typescript/module/components/timed-event-container.d.ts.map +1 -0
  172. package/lib/typescript/module/components/timed-events.d.ts +7 -0
  173. package/lib/typescript/module/components/timed-events.d.ts.map +1 -0
  174. package/lib/typescript/module/components/zoom-provider.d.ts +7 -0
  175. package/lib/typescript/module/components/zoom-provider.d.ts.map +1 -0
  176. package/lib/typescript/module/enums.d.ts +2 -0
  177. package/lib/typescript/module/enums.d.ts.map +1 -0
  178. package/lib/typescript/module/hooks/use-cloned-events.d.ts +11 -0
  179. package/lib/typescript/module/hooks/use-cloned-events.d.ts.map +1 -0
  180. package/lib/typescript/module/hooks/use-events-layout.d.ts +13 -0
  181. package/lib/typescript/module/hooks/use-events-layout.d.ts.map +1 -0
  182. package/lib/typescript/module/hooks/use-is-editing.d.ts +17 -0
  183. package/lib/typescript/module/hooks/use-is-editing.d.ts.map +1 -0
  184. package/lib/typescript/module/index.d.ts +27 -0
  185. package/lib/typescript/module/index.d.ts.map +1 -0
  186. package/lib/typescript/module/package.json +1 -0
  187. package/lib/typescript/module/types.d.ts +128 -0
  188. package/lib/typescript/module/types.d.ts.map +1 -0
  189. package/lib/typescript/module/utils/__tests___/compute-positioning.test.d.ts +2 -0
  190. package/lib/typescript/module/utils/__tests___/compute-positioning.test.d.ts.map +1 -0
  191. package/lib/typescript/module/utils/__tests___/date-utils.test.d.ts +2 -0
  192. package/lib/typescript/module/utils/__tests___/date-utils.test.d.ts.map +1 -0
  193. package/lib/typescript/module/utils/__tests___/generate-event-layout.test.d.ts +2 -0
  194. package/lib/typescript/module/utils/__tests___/generate-event-layout.test.d.ts.map +1 -0
  195. package/lib/typescript/module/utils/calendar-layout.d.ts +36 -0
  196. package/lib/typescript/module/utils/calendar-layout.d.ts.map +1 -0
  197. package/lib/typescript/module/utils/compute-positioning.d.ts +10 -0
  198. package/lib/typescript/module/utils/compute-positioning.d.ts.map +1 -0
  199. package/lib/typescript/module/utils/date-utils.d.ts +30 -0
  200. package/lib/typescript/module/utils/date-utils.d.ts.map +1 -0
  201. package/lib/typescript/module/utils/double-tap-reset-zoom-gesture.d.ts +5 -0
  202. package/lib/typescript/module/utils/double-tap-reset-zoom-gesture.d.ts.map +1 -0
  203. package/lib/typescript/module/utils/generate-event-layouts.d.ts +15 -0
  204. package/lib/typescript/module/utils/generate-event-layouts.d.ts.map +1 -0
  205. package/lib/typescript/module/utils/globals.d.ts +5 -0
  206. package/lib/typescript/module/utils/globals.d.ts.map +1 -0
  207. package/lib/typescript/module/utils/pan-edit-event-gesture.d.ts +6 -0
  208. package/lib/typescript/module/utils/pan-edit-event-gesture.d.ts.map +1 -0
  209. package/package.json +195 -0
  210. package/src/components/all-day-events.tsx +134 -0
  211. package/src/components/background-hours-content.tsx +51 -0
  212. package/src/components/background-hours-layout.tsx +61 -0
  213. package/src/components/drag-bar.tsx +120 -0
  214. package/src/components/edit-event-container.tsx +158 -0
  215. package/src/components/event-container.tsx +44 -0
  216. package/src/components/new-event-container.tsx +90 -0
  217. package/src/components/time-indicator.tsx +72 -0
  218. package/src/components/timed-event-container.tsx +124 -0
  219. package/src/components/timed-events.tsx +72 -0
  220. package/src/components/zoom-provider.tsx +146 -0
  221. package/src/enums.ts +0 -0
  222. package/src/hooks/use-cloned-events.ts +26 -0
  223. package/src/hooks/use-events-layout.ts +55 -0
  224. package/src/hooks/use-is-editing.tsx +109 -0
  225. package/src/index.tsx +165 -0
  226. package/src/types.ts +163 -0
  227. package/src/utils/__tests___/compute-positioning.test.ts +255 -0
  228. package/src/utils/__tests___/date-utils.test.ts +41 -0
  229. package/src/utils/__tests___/generate-event-layout.test.ts +277 -0
  230. package/src/utils/calendar-layout.ts +139 -0
  231. package/src/utils/compute-positioning.ts +44 -0
  232. package/src/utils/date-utils.ts +238 -0
  233. package/src/utils/double-tap-reset-zoom-gesture.ts +23 -0
  234. package/src/utils/generate-event-layouts.ts +314 -0
  235. package/src/utils/globals.ts +8 -0
  236. 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,8 @@
1
+ import { createContext } from "react";
2
+ import { Config } from "src/types";
3
+
4
+ export const ConfigProvider = createContext<Config>(undefined as never);
5
+
6
+ export const DEFAULT_MINUTE_HEIGHT = 0.8;
7
+
8
+ export const TOP_MARGIN_PIXEL_OFFSET = 5;
@@ -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;