@sunsama/event-calendar 0.8.3 → 0.10.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 (43) hide show
  1. package/README.md +3 -0
  2. package/lib/commonjs/components/edit-event-container.js +13 -1
  3. package/lib/commonjs/components/edit-event-container.js.map +1 -1
  4. package/lib/commonjs/components/timed-event-container.js +13 -1
  5. package/lib/commonjs/components/timed-event-container.js.map +1 -1
  6. package/lib/commonjs/hooks/use-is-editing.js +51 -7
  7. package/lib/commonjs/hooks/use-is-editing.js.map +1 -1
  8. package/lib/commonjs/index.js +19 -5
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/types.js +3 -2
  11. package/lib/commonjs/types.js.map +1 -1
  12. package/lib/module/components/edit-event-container.js +13 -1
  13. package/lib/module/components/edit-event-container.js.map +1 -1
  14. package/lib/module/components/timed-event-container.js +14 -2
  15. package/lib/module/components/timed-event-container.js.map +1 -1
  16. package/lib/module/hooks/use-is-editing.js +52 -8
  17. package/lib/module/hooks/use-is-editing.js.map +1 -1
  18. package/lib/module/index.js +19 -5
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/types.js +3 -2
  21. package/lib/module/types.js.map +1 -1
  22. package/lib/typescript/commonjs/components/edit-event-container.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/components/timed-event-container.d.ts.map +1 -1
  24. package/lib/typescript/commonjs/hooks/use-is-editing.d.ts +12 -3
  25. package/lib/typescript/commonjs/hooks/use-is-editing.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/index.d.ts +3 -0
  27. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/types.d.ts +4 -2
  29. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  30. package/lib/typescript/module/components/edit-event-container.d.ts.map +1 -1
  31. package/lib/typescript/module/components/timed-event-container.d.ts.map +1 -1
  32. package/lib/typescript/module/hooks/use-is-editing.d.ts +12 -3
  33. package/lib/typescript/module/hooks/use-is-editing.d.ts.map +1 -1
  34. package/lib/typescript/module/index.d.ts +3 -0
  35. package/lib/typescript/module/index.d.ts.map +1 -1
  36. package/lib/typescript/module/types.d.ts +4 -2
  37. package/lib/typescript/module/types.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/src/components/edit-event-container.tsx +19 -1
  40. package/src/components/timed-event-container.tsx +25 -1
  41. package/src/hooks/use-is-editing.tsx +90 -8
  42. package/src/index.tsx +29 -5
  43. package/src/types.ts +2 -0
@@ -1,22 +1,27 @@
1
1
  import React, {
2
2
  createContext,
3
+ forwardRef,
3
4
  ReactNode,
5
+ type Ref,
4
6
  useCallback,
5
7
  useContext,
8
+ useImperativeHandle,
6
9
  useState,
7
10
  } from "react";
8
11
  import { SharedValue, useSharedValue } from "react-native-reanimated";
9
12
  import { ConfigProvider } from "../utils/globals";
10
- import { isFunction } from "lodash";
13
+ import { debounce, isFunction } from "lodash";
11
14
  import {
12
15
  type CalendarEvent,
13
16
  EditStatus,
14
17
  PartDayEventLayoutType,
15
18
  } from "../types";
16
19
  import { useEvents } from "./use-events";
20
+ import moment from "moment-timezone";
17
21
 
18
22
  interface IsEditingType<T extends CalendarEvent> {
19
23
  isEditing: null | PartDayEventLayoutType<T>;
24
+ updateEditing: (top: number, height: number) => void;
20
25
  currentY: SharedValue<number>;
21
26
  setIsEditing: (
22
27
  newValue: PartDayEventLayoutType<T> | null,
@@ -38,19 +43,54 @@ export const useIsEditing = () => {
38
43
  return context;
39
44
  };
40
45
 
41
- // Provider component
42
- export const IsEditingProvider = <T extends CalendarEvent>({
43
- children,
44
- }: {
46
+ type IsEditingProviderInnerProps = {
45
47
  children: ReactNode;
46
- }) => {
47
- const { canEditEvent, onEventEdit, updateLocalStateAfterEdit } =
48
+ };
49
+
50
+ export type IsEditingProviderInnerMethods<T extends CalendarEvent> = {
51
+ startEditing: (layout: PartDayEventLayoutType<T>) => void;
52
+ endEditing: () => void;
53
+ };
54
+
55
+ const IsEditingProviderInner = <T extends CalendarEvent>(
56
+ { children }: IsEditingProviderInnerProps,
57
+ refMethods: Ref<IsEditingProviderInnerMethods<T>>
58
+ ) => {
59
+ const { canEditEvent, onEventEdit, updateLocalStateAfterEdit, timezone } =
48
60
  useContext(ConfigProvider);
49
61
  const { updateClonedEvents } = useEvents();
50
62
  const [isEditing, baseSetIsEditing] =
51
63
  useState<null | PartDayEventLayoutType<T>>(null);
52
64
  const currentY = useSharedValue(0);
53
65
 
66
+ const updateEditing = debounce(
67
+ (start: number, end: number) => {
68
+ if (!isEditing) {
69
+ return;
70
+ }
71
+
72
+ const newStart = moment
73
+ .tz(isEditing.event.start, timezone)
74
+ .startOf("day")
75
+ .add(start, "minutes");
76
+ const newEnd = moment
77
+ .tz(isEditing.event.start, timezone)
78
+ .startOf("day")
79
+ .add(end, "minutes");
80
+
81
+ onEventEdit?.({
82
+ event: isEditing.event,
83
+ status: EditStatus.Update,
84
+ updatedTimes: {
85
+ updatedStart: newStart.format(),
86
+ updatedEnd: newEnd.format(),
87
+ },
88
+ });
89
+ },
90
+ 500,
91
+ { trailing: true }
92
+ );
93
+
54
94
  const setIsEditing = useCallback(
55
95
  (
56
96
  newValue: PartDayEventLayoutType<T> | null,
@@ -115,9 +155,51 @@ export const IsEditingProvider = <T extends CalendarEvent>({
115
155
  ]
116
156
  );
117
157
 
158
+ useImperativeHandle(
159
+ refMethods,
160
+ () => ({
161
+ endEditing: () => {
162
+ if (!isEditing) {
163
+ return;
164
+ }
165
+
166
+ onEventEdit?.({
167
+ event: isEditing?.event,
168
+ status: EditStatus.Finish,
169
+ });
170
+ baseSetIsEditing(null);
171
+ },
172
+ startEditing: (layout) => {
173
+ if (isEditing) {
174
+ onEventEdit?.({
175
+ event: isEditing.event,
176
+ status: EditStatus.Finish,
177
+ });
178
+ }
179
+
180
+ onEventEdit?.({
181
+ event: layout.event,
182
+ status: EditStatus.Start,
183
+ });
184
+ baseSetIsEditing(layout);
185
+ },
186
+ }),
187
+ [baseSetIsEditing, isEditing, onEventEdit]
188
+ );
189
+
118
190
  return (
119
- <IsEditing.Provider value={{ currentY, isEditing, setIsEditing }}>
191
+ <IsEditing.Provider
192
+ value={{ currentY, isEditing, setIsEditing, updateEditing }}
193
+ >
120
194
  {children}
121
195
  </IsEditing.Provider>
122
196
  );
123
197
  };
198
+
199
+ export const IsEditingProvider = forwardRef(IsEditingProviderInner) as <
200
+ T extends CalendarEvent,
201
+ >(
202
+ props: IsEditingProviderInnerProps & {
203
+ ref?: Ref<IsEditingProviderInnerMethods<T>>;
204
+ }
205
+ ) => ReturnType<typeof IsEditingProviderInner>;
package/src/index.tsx CHANGED
@@ -23,7 +23,10 @@ import React, {
23
23
  useRef,
24
24
  } from "react";
25
25
  import { GestureRef } from "react-native-gesture-handler/lib/typescript/handlers/gestures/gesture";
26
- import { IsEditingProvider } from "./hooks/use-is-editing";
26
+ import {
27
+ IsEditingProvider,
28
+ type IsEditingProviderInnerMethods,
29
+ } from "./hooks/use-is-editing";
27
30
  import { EventsProvider, useEvents } from "./hooks/use-events";
28
31
  import type { CalendarEvent, Config, onCreateEvent, ThemeStyle } from "./types";
29
32
  import {
@@ -35,6 +38,7 @@ import type { NativeScrollEvent } from "react-native/Libraries/Components/Scroll
35
38
  export * from "./types";
36
39
 
37
40
  type EventCalenderProps<T extends CalendarEvent> = {
41
+ initialEventEdit?: string;
38
42
  onScroll?: (y: number) => void;
39
43
  canCreateEvents?: boolean;
40
44
  canEditEvent?: Config<T>["canEditEvent"];
@@ -63,6 +67,7 @@ type EventCalenderProps<T extends CalendarEvent> = {
63
67
  };
64
68
 
65
69
  type EventCalenderContentProps<T extends CalendarEvent> = {
70
+ initialEventEdit?: string;
66
71
  onScroll?: (y: number) => void;
67
72
  canCreateEvents: boolean;
68
73
  canEditEvent: Config<T>["canEditEvent"];
@@ -91,10 +96,13 @@ type EventCalenderContentProps<T extends CalendarEvent> = {
91
96
  export type EventCalendarMethods = {
92
97
  scrollToTime: (minutes: number, animated?: boolean, offset?: number) => void;
93
98
  scrollToOffset: (y: number, animated?: boolean) => void;
99
+ startEditMode: (eventId: string) => void;
100
+ endEditMode: () => void;
94
101
  };
95
102
 
96
103
  function EventCalendarContentInner<T extends CalendarEvent>(
97
104
  {
105
+ initialEventEdit,
98
106
  canCreateEvents,
99
107
  canEditEvent,
100
108
  fiveMinuteInterval,
@@ -128,11 +136,14 @@ function EventCalendarContentInner<T extends CalendarEvent>(
128
136
  const refNewEvent = useRef<GestureRef>(null);
129
137
  const refScrollView = useRef<ScrollView>(null);
130
138
  const refScrollViewHeight = useRef<number>(0);
139
+ const refEditingProvider = useRef<IsEditingProviderInnerMethods<T>>(null);
131
140
 
132
141
  const onLayoutScrollView = useCallback((event: LayoutChangeEvent) => {
133
142
  refScrollViewHeight.current = event.nativeEvent.layout.height;
134
143
  }, []);
135
144
 
145
+ const { eventsLayout } = useEvents();
146
+
136
147
  useImperativeHandle(
137
148
  refMethods,
138
149
  () => ({
@@ -148,8 +159,22 @@ function EventCalendarContentInner<T extends CalendarEvent>(
148
159
  animated,
149
160
  });
150
161
  },
162
+ endEditMode: () => {
163
+ refEditingProvider.current?.endEditing();
164
+ },
165
+ startEditMode: (eventId: string) => {
166
+ const layout = eventsLayout.partDayEventsLayout.find(
167
+ (item) => item.event.id === eventId
168
+ );
169
+
170
+ if (!layout) {
171
+ return;
172
+ }
173
+
174
+ refEditingProvider.current?.startEditing(layout);
175
+ },
151
176
  }),
152
- [zoomLevel]
177
+ [zoomLevel, eventsLayout]
153
178
  );
154
179
 
155
180
  const onScrollFeedback = useCallback(
@@ -159,8 +184,6 @@ function EventCalendarContentInner<T extends CalendarEvent>(
159
184
  [onScroll]
160
185
  );
161
186
 
162
- const { eventsLayout } = useEvents();
163
-
164
187
  return (
165
188
  <View style={[styles.container, theme?.container]}>
166
189
  <ConfigProvider.Provider
@@ -191,6 +214,7 @@ function EventCalendarContentInner<T extends CalendarEvent>(
191
214
  onZoomChange,
192
215
  updateLocalStateAfterEdit,
193
216
  theme,
217
+ initialEventEdit,
194
218
  }}
195
219
  >
196
220
  <AllDayEvents />
@@ -202,7 +226,7 @@ function EventCalendarContentInner<T extends CalendarEvent>(
202
226
  ref={refScrollView}
203
227
  onScroll={onScrollFeedback}
204
228
  >
205
- <IsEditingProvider>
229
+ <IsEditingProvider ref={refEditingProvider}>
206
230
  <ZoomProvider ref={refNewEvent}>
207
231
  <View style={[styles.borderContainer, theme?.borderContainer]} />
208
232
  <TimedEvents refNewEvent={refNewEvent} />
package/src/types.ts CHANGED
@@ -98,6 +98,7 @@ export interface OnEventEditParams<T extends CalendarEvent> {
98
98
  }
99
99
 
100
100
  export type Config<T extends CalendarEvent> = {
101
+ initialEventEdit?: string;
101
102
  timezone: string;
102
103
  timeFormat: string;
103
104
  dayDate: Moment;
@@ -164,6 +165,7 @@ export enum EventExtend {
164
165
 
165
166
  export enum EditStatus {
166
167
  Start,
168
+ Update,
167
169
  Finish,
168
170
  Delete,
169
171
  }