@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,51 @@
1
+ import { memo, useContext } from "react";
2
+ import Animated, { useAnimatedStyle } from "react-native-reanimated";
3
+ import { StyleSheet } from "react-native";
4
+ import { ConfigProvider } from "src/utils/globals";
5
+ import { PrefabHour } from "src/types";
6
+
7
+ type BackgroundHoursContentProps = {
8
+ hours: PrefabHour[];
9
+ };
10
+
11
+ const BackgroundHoursContent = memo(
12
+ ({ hours }: BackgroundHoursContentProps) => {
13
+ const { theme, zoomLevel } = useContext(ConfigProvider);
14
+
15
+ const styleHourSize = useAnimatedStyle(() => {
16
+ return { height: zoomLevel.value * 60 };
17
+ }, []);
18
+
19
+ return (
20
+ <>
21
+ {hours.map((hour) => (
22
+ <Animated.View
23
+ style={[
24
+ styles.hourContainer,
25
+ hour === hours[hours.length - 1]
26
+ ? styles.bottomBorder
27
+ : undefined,
28
+ theme?.backgroundHoursLayoutContainer,
29
+ styleHourSize,
30
+ ]}
31
+ key={hour.increment}
32
+ />
33
+ ))}
34
+ </>
35
+ );
36
+ },
37
+ () => true
38
+ );
39
+
40
+ const styles = StyleSheet.create({
41
+ hourContainer: {
42
+ borderTopWidth: StyleSheet.hairlineWidth,
43
+ marginRight: -20,
44
+ borderColor: "black",
45
+ },
46
+ bottomBorder: {
47
+ borderBottomWidth: StyleSheet.hairlineWidth,
48
+ },
49
+ });
50
+
51
+ export default BackgroundHoursContent;
@@ -0,0 +1,61 @@
1
+ import { memo, useContext } from "react";
2
+ import Animated, { useAnimatedStyle } from "react-native-reanimated";
3
+ import { StyleSheet, Text, View } from "react-native";
4
+ import { ConfigProvider } from "src/utils/globals";
5
+ import { PrefabHour } from "src/types";
6
+
7
+ type BackgroundHoursLayoutProps = {
8
+ hours: PrefabHour[];
9
+ };
10
+
11
+ const BackgroundHoursLayout = memo(
12
+ ({ hours }: BackgroundHoursLayoutProps) => {
13
+ const { theme, zoomLevel } = useContext(ConfigProvider);
14
+
15
+ const styleHourSize = useAnimatedStyle(() => {
16
+ return { height: zoomLevel.value * 60 };
17
+ }, []);
18
+
19
+ return (
20
+ <View style={[styles.hourContainer, theme?.backgroundHoursContainer]}>
21
+ {hours.map((hour) => (
22
+ <Animated.View
23
+ style={[
24
+ styles.hourInnerContainer,
25
+ theme?.backgroundHoursInnerContainer,
26
+ styleHourSize,
27
+ ]}
28
+ key={hour.increment}
29
+ >
30
+ <Text style={[styles.hourText, theme?.backgroundHoursText]}>
31
+ {hour.hourFormatted}
32
+ </Text>
33
+ </Animated.View>
34
+ ))}
35
+ </View>
36
+ );
37
+ },
38
+ () => true
39
+ );
40
+
41
+ const styles = StyleSheet.create({
42
+ hourContainer: {
43
+ flexDirection: "column",
44
+ flexGrow: 0,
45
+ flexShrink: 0,
46
+ flexBasis: 50,
47
+ paddingRight: 6,
48
+ },
49
+ hourInnerContainer: {
50
+ marginTop: -12,
51
+ marginBottom: 12,
52
+ marginRight: 0,
53
+ },
54
+ hourText: {
55
+ textAlign: "right",
56
+ color: "black",
57
+ fontSize: 10,
58
+ },
59
+ });
60
+
61
+ export default BackgroundHoursLayout;
@@ -0,0 +1,120 @@
1
+ import Animated, { SharedValue, useSharedValue } from "react-native-reanimated";
2
+ import { ReactNode, useMemo } from "react";
3
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
4
+ import { StyleSheet } from "react-native";
5
+
6
+ type DragBarProps = {
7
+ top?: SharedValue<number>;
8
+ height: SharedValue<number>;
9
+ render: () => ReactNode;
10
+ refMainContainer: React.RefObject<any>;
11
+ fiveMinuteInterval?: boolean;
12
+ zoomLevel: SharedValue<number>;
13
+ maximumHour: SharedValue<number>;
14
+ };
15
+
16
+ const DragBar = ({
17
+ top,
18
+ height,
19
+ render,
20
+ refMainContainer,
21
+ fiveMinuteInterval,
22
+ zoomLevel,
23
+ maximumHour,
24
+ }: DragBarProps) => {
25
+ const startY = useSharedValue(0);
26
+
27
+ const gesturePan = Gesture.Pan()
28
+ .blocksExternalGesture(refMainContainer)
29
+ .onStart(() => {
30
+ startY.value = top ? top.value : height.value;
31
+ })
32
+ .onUpdate(({ translationY }) => {
33
+ if (top) {
34
+ const originalY = top.value;
35
+
36
+ let freshUpdatedStartTime;
37
+
38
+ if (fiveMinuteInterval) {
39
+ // Set the updated time in 15 minute increments but make sure we never go lower
40
+ // than the first minute of the day
41
+ freshUpdatedStartTime = Math.max(
42
+ 0,
43
+ startY.value +
44
+ Math.floor(translationY / zoomLevel.value / 5) *
45
+ (zoomLevel.value * 5)
46
+ );
47
+ } else {
48
+ // Set the updated time in 1 minute increments but make sure we never go lower
49
+ // than the first minute of the day
50
+ freshUpdatedStartTime = Math.max(
51
+ 0,
52
+ startY.value +
53
+ Math.floor(translationY / zoomLevel.value) * zoomLevel.value
54
+ );
55
+ }
56
+
57
+ // Make sure the event does not span after midnight, and if so make sure it
58
+ // is limited to exactly midnight
59
+ if (freshUpdatedStartTime > maximumHour.value - height.value) {
60
+ freshUpdatedStartTime = maximumHour.value - height.value;
61
+ }
62
+
63
+ top.value = freshUpdatedStartTime;
64
+ height.value = height.value + (originalY - top.value);
65
+
66
+ return;
67
+ }
68
+
69
+ let freshUpdatedEndTime;
70
+
71
+ if (fiveMinuteInterval) {
72
+ // Set the updated time in 15 minute increments but make sure we never go lower
73
+ // than the first minute of the day
74
+ freshUpdatedEndTime = Math.max(
75
+ 0,
76
+ startY.value +
77
+ Math.floor(translationY / zoomLevel.value / 5) *
78
+ (zoomLevel.value * 5)
79
+ );
80
+ } else {
81
+ // Set the updated time in 1 minute increments but make sure we never go lower
82
+ // than the first minute of the day
83
+ freshUpdatedEndTime = Math.max(
84
+ 0,
85
+ startY.value +
86
+ Math.floor(translationY / zoomLevel.value) * zoomLevel.value
87
+ );
88
+ }
89
+
90
+ height.value = freshUpdatedEndTime;
91
+ });
92
+
93
+ const styleDragBar = useMemo(
94
+ () => ({
95
+ bottom: !top ? 0 : undefined,
96
+ top: top ? 0 : undefined,
97
+ }),
98
+ [top]
99
+ );
100
+
101
+ const renderedComponent = useMemo(render, [render]);
102
+
103
+ return (
104
+ <GestureDetector gesture={gesturePan}>
105
+ <Animated.View style={[styles.dragBar, styleDragBar]}>
106
+ {renderedComponent}
107
+ </Animated.View>
108
+ </GestureDetector>
109
+ );
110
+ };
111
+
112
+ export default DragBar;
113
+
114
+ const styles = StyleSheet.create({
115
+ dragBar: {
116
+ position: "absolute",
117
+ left: 0,
118
+ right: 0,
119
+ },
120
+ });
@@ -0,0 +1,158 @@
1
+ import {
2
+ memo,
3
+ RefObject,
4
+ useCallback,
5
+ useContext,
6
+ useEffect,
7
+ useRef,
8
+ } from "react";
9
+ import { useIsEditing } from "src/hooks/use-is-editing";
10
+ import { ConfigProvider } from "src/utils/globals";
11
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
12
+ import Animated, {
13
+ runOnJS,
14
+ useAnimatedReaction,
15
+ useAnimatedStyle,
16
+ useDerivedValue,
17
+ useSharedValue,
18
+ } from "react-native-reanimated";
19
+ import { EventExtend } from "src/types";
20
+ import gesturePan from "src/utils/pan-edit-event-gesture";
21
+ import DragBar from "src/components/drag-bar";
22
+ import { StyleSheet } from "react-native";
23
+ import moment from "moment-timezone";
24
+
25
+ type EditEventContainerProps = {
26
+ refNewEvent: RefObject<any>;
27
+ };
28
+
29
+ const EditEventContainer = memo(
30
+ ({ refNewEvent }: EditEventContainerProps) => {
31
+ const { currentY, isEditing: editingEvent, setIsEditing } = useIsEditing();
32
+ const {
33
+ maximumHour,
34
+ fiveMinuteInterval,
35
+ renderDragBars,
36
+ zoomLevel,
37
+ renderEvent,
38
+ timezone,
39
+ dayDate,
40
+ } = useContext(ConfigProvider);
41
+ const height = useSharedValue(0);
42
+
43
+ useEffect(() => {
44
+ if (editingEvent) {
45
+ height.value = editingEvent.position.height * zoomLevel.value;
46
+ currentY.value = editingEvent.position.top * zoomLevel.value;
47
+ }
48
+ }, [height, editingEvent, currentY, zoomLevel]);
49
+
50
+ useAnimatedReaction(
51
+ () => zoomLevel.value,
52
+ (zoom) => {
53
+ if (editingEvent) {
54
+ height.value = editingEvent.position.height * zoom;
55
+ currentY.value = editingEvent.position.top * zoom;
56
+ }
57
+ },
58
+ [height, currentY, zoomLevel, editingEvent]
59
+ );
60
+
61
+ const styleAnimatedPosition = useAnimatedStyle(() => {
62
+ if (!editingEvent) {
63
+ return { opacity: 0 };
64
+ }
65
+
66
+ return {
67
+ marginLeft: StyleSheet.hairlineWidth,
68
+ position: "absolute",
69
+ height: height.value,
70
+ top: currentY.value,
71
+ opacity: 1,
72
+ width: "100%",
73
+ };
74
+ }, [editingEvent]);
75
+
76
+ const startY = useSharedValue(0);
77
+
78
+ const updatedStart = useDerivedValue(() => {
79
+ return currentY.value / zoomLevel.value;
80
+ }, []);
81
+
82
+ const updatedEnd = useDerivedValue(() => {
83
+ return (currentY.value + height.value) / zoomLevel.value;
84
+ }, []);
85
+
86
+ const endEventEditing = useCallback(
87
+ (newStart: number, newEnd: number) => {
88
+ // Format the new start and end times
89
+ setIsEditing(null, {
90
+ updatedStart: moment.tz(dayDate, timezone).minutes(newStart).format(),
91
+ updatedEnd: moment.tz(dayDate, timezone).minutes(newEnd).format(),
92
+ });
93
+ },
94
+ [dayDate, setIsEditing, timezone]
95
+ );
96
+
97
+ const gestureTap = Gesture.Tap()
98
+ .numberOfTaps(1)
99
+ .onStart(() => {
100
+ runOnJS(endEventEditing)(updatedStart.value, updatedEnd.value);
101
+ });
102
+
103
+ const refMainContainer = useRef();
104
+
105
+ if (!editingEvent) {
106
+ return null;
107
+ }
108
+
109
+ return (
110
+ <GestureDetector
111
+ gesture={Gesture.Simultaneous(
112
+ gestureTap,
113
+ gesturePan(
114
+ startY,
115
+ currentY,
116
+ currentY,
117
+ zoomLevel,
118
+ maximumHour,
119
+ height,
120
+ refNewEvent,
121
+ fiveMinuteInterval
122
+ ).withRef(refMainContainer)
123
+ )}
124
+ >
125
+ <Animated.View style={styleAnimatedPosition}>
126
+ {renderEvent(editingEvent.event, EventExtend.None, height, {
127
+ updatedEnd,
128
+ updatedStart,
129
+ })}
130
+ {renderDragBars?.top ? (
131
+ <DragBar
132
+ top={currentY}
133
+ height={height}
134
+ render={renderDragBars.top}
135
+ refMainContainer={refMainContainer}
136
+ zoomLevel={zoomLevel}
137
+ maximumHour={maximumHour}
138
+ fiveMinuteInterval={fiveMinuteInterval}
139
+ />
140
+ ) : null}
141
+ {renderDragBars?.bottom ? (
142
+ <DragBar
143
+ height={height}
144
+ render={renderDragBars.bottom}
145
+ refMainContainer={refMainContainer}
146
+ zoomLevel={zoomLevel}
147
+ maximumHour={maximumHour}
148
+ fiveMinuteInterval={fiveMinuteInterval}
149
+ />
150
+ ) : null}
151
+ </Animated.View>
152
+ </GestureDetector>
153
+ );
154
+ },
155
+ () => true
156
+ );
157
+
158
+ export default EditEventContainer;
@@ -0,0 +1,44 @@
1
+ import { ConfigProvider } from "src/utils/globals";
2
+ import { useCallback, useContext, useMemo } from "react";
3
+ import { Pressable } from "react-native-gesture-handler";
4
+ import { View } from "react-native";
5
+ import { AllDayEventLayoutType, EventExtend } from "src/types";
6
+
7
+ type EventContainerProps = {
8
+ layout: AllDayEventLayoutType;
9
+ };
10
+
11
+ const EventContainer = ({ layout }: EventContainerProps) => {
12
+ const { onPressEvent, renderEvent, initialZoomLevel } =
13
+ useContext(ConfigProvider);
14
+
15
+ const render = useMemo(
16
+ () =>
17
+ renderEvent(
18
+ layout.event,
19
+ (layout as AllDayEventLayoutType).extend
20
+ ? (layout as AllDayEventLayoutType).extend
21
+ : EventExtend.None
22
+ ),
23
+ [layout, renderEvent]
24
+ );
25
+
26
+ const stylePosition = useMemo(
27
+ () => ({
28
+ height: Math.max(28, 24 * initialZoomLevel),
29
+ }),
30
+ [initialZoomLevel]
31
+ );
32
+
33
+ const onPress = useCallback(() => {
34
+ onPressEvent && onPressEvent(layout.event);
35
+ }, [layout.event, onPressEvent]);
36
+
37
+ return (
38
+ <Pressable onPress={onPress}>
39
+ <View style={stylePosition}>{render}</View>
40
+ </Pressable>
41
+ );
42
+ };
43
+
44
+ export default EventContainer;
@@ -0,0 +1,90 @@
1
+ import { memo, useContext, useMemo, useState } from "react";
2
+ import { ConfigProvider, TOP_MARGIN_PIXEL_OFFSET } from "src/utils/globals";
3
+ import Animated, {
4
+ runOnJS,
5
+ useAnimatedReaction,
6
+ useAnimatedStyle,
7
+ } from "react-native-reanimated";
8
+ import { StyleSheet, View } from "react-native";
9
+ import { useIsEditing } from "src/hooks/use-is-editing";
10
+
11
+ const NewEventContainer = memo(
12
+ () => {
13
+ const {
14
+ fiveMinuteInterval,
15
+ renderNewEventContainer,
16
+ zoomLevel,
17
+ createY,
18
+ theme,
19
+ } = useContext(ConfigProvider);
20
+
21
+ const { isEditing } = useIsEditing();
22
+
23
+ const styleVisible = useAnimatedStyle(() => {
24
+ return {
25
+ opacity: !isEditing && createY.value >= 0 ? 1 : 0,
26
+ transform: [
27
+ {
28
+ translateY: createY.value - TOP_MARGIN_PIXEL_OFFSET,
29
+ },
30
+ ],
31
+ height: zoomLevel.value * 60,
32
+ };
33
+ }, [isEditing]);
34
+
35
+ const [[hour, minute], setTime] = useState([0, 0]);
36
+
37
+ const hasRenderEvent = useMemo(
38
+ () => !!renderNewEventContainer,
39
+ [renderNewEventContainer]
40
+ );
41
+
42
+ useAnimatedReaction(
43
+ () => ({ zoomLevel: zoomLevel.value, createY: createY.value }),
44
+ (state) => {
45
+ if (!hasRenderEvent) {
46
+ return;
47
+ }
48
+
49
+ const freshTime = Math.floor(state.createY / state.zoomLevel);
50
+ const freshHour = Math.floor(freshTime / 60);
51
+ const freshMinute = !fiveMinuteInterval
52
+ ? freshTime - freshHour * 60
53
+ : Math.round(freshTime / 5) * 5 - freshHour * 60;
54
+
55
+ runOnJS(setTime)([freshHour, freshMinute]);
56
+ },
57
+ []
58
+ );
59
+
60
+ return (
61
+ <Animated.View style={[styles.container, styleVisible]}>
62
+ {renderNewEventContainer ? (
63
+ renderNewEventContainer(hour, minute)
64
+ ) : (
65
+ <View style={[styles.defaultContainer, theme?.newEventContainer]} />
66
+ )}
67
+ </Animated.View>
68
+ );
69
+ },
70
+ () => true
71
+ );
72
+
73
+ export default NewEventContainer;
74
+
75
+ const styles = StyleSheet.create({
76
+ container: {
77
+ position: "absolute",
78
+ top: 0,
79
+ left: 51,
80
+ right: 10,
81
+ height: 50,
82
+ },
83
+ defaultContainer: {
84
+ flex: 1,
85
+ borderRadius: 3,
86
+ padding: 5,
87
+ backgroundColor: "pink",
88
+ opacity: 0.8,
89
+ },
90
+ });
@@ -0,0 +1,72 @@
1
+ import { memo, useCallback, useContext, useEffect } from "react";
2
+ import Animated, {
3
+ useAnimatedStyle,
4
+ useSharedValue,
5
+ } from "react-native-reanimated";
6
+ import { ConfigProvider } from "src/utils/globals";
7
+ import moment from "moment-timezone";
8
+ import { AppState, StyleSheet } from "react-native";
9
+
10
+ const TimeIndicator = memo(
11
+ () => {
12
+ const { zoomLevel, timezone, theme } = useContext(ConfigProvider);
13
+
14
+ const currentMinutes = useCallback(() => {
15
+ const time = moment.tz(timezone);
16
+
17
+ return time.minutes() + time.hours() * 60;
18
+ }, [timezone]);
19
+
20
+ const currentMoment = useSharedValue<number>(currentMinutes());
21
+
22
+ useEffect(() => {
23
+ let interval = setInterval(() => {
24
+ currentMoment.value = currentMinutes();
25
+ }, 20000);
26
+
27
+ const subscription = AppState.addEventListener(
28
+ "change",
29
+ (appState: string) => {
30
+ clearInterval(interval);
31
+
32
+ if (appState === "active") {
33
+ interval = setInterval(() => {
34
+ currentMoment.value = currentMinutes();
35
+ }, 20000);
36
+ }
37
+ }
38
+ );
39
+
40
+ return () => {
41
+ clearInterval(interval);
42
+ subscription.remove();
43
+ };
44
+ }, [currentMinutes, currentMoment]);
45
+
46
+ const style = useAnimatedStyle(() => ({
47
+ top: zoomLevel.value * currentMoment.value,
48
+ }));
49
+
50
+ return (
51
+ <Animated.View
52
+ style={[styles.timeIndicator, style, theme?.timeIndicator]}
53
+ />
54
+ );
55
+ },
56
+ () => true
57
+ );
58
+
59
+ export default TimeIndicator;
60
+
61
+ const styles = StyleSheet.create({
62
+ timeIndicator: {
63
+ position: "absolute",
64
+ left: 0,
65
+ width: "110%",
66
+ borderTopWidth: 2,
67
+ borderTopColor: "#f25a43",
68
+ zIndex: 2,
69
+ elevation: 2,
70
+ opacity: 0.6,
71
+ },
72
+ });