react-native-resource-calendar 1.0.9 → 1.0.11

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/README.md CHANGED
@@ -7,7 +7,7 @@ Expo compatibility.
7
7
 
8
8
  ## ✨ Features
9
9
 
10
- - ✅ Multi-resource timeline layout
10
+ - ✅ Multi-resource/multi-days timeline layout
11
11
  - 🎨 Customizable event slots (Body, TopRight)
12
12
  - 📱 Smooth Reanimated drag-and-drop
13
13
  - ⏰ Timezone-aware time labels
@@ -18,6 +18,7 @@ Expo compatibility.
18
18
  ---
19
19
 
20
20
  ## 🎬 Demo
21
+
21
22
  https://github.com/user-attachments/assets/68fe0283-73ce-4689-8241-6587b817ecbd
22
23
 
23
24
  ---
@@ -75,10 +76,10 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native';
75
76
  import {Calendar, DraggedEventDraft, Event, LayoutMode, useCalendarBinding} from "react-native-resource-calendar";
76
77
  import {SafeAreaView} from "react-native-safe-area-context";
77
78
  import {ThemedText} from "@/components/ThemedText";
78
- import {resourceData} from "@/app/(tabs)/fakeData";
79
79
  import EventTopRight from "@/components/EventTopRight";
80
80
  import {FontAwesome} from "@expo/vector-icons";
81
81
  import {statusColor} from "@/utilities/helpers";
82
+ import {resourceData} from "@/assets/fakeData";
82
83
 
83
84
  export default function App() {
84
85
  const {
@@ -98,27 +99,34 @@ export default function App() {
98
99
  const updateResourcesOnDrag = React.useCallback(
99
100
  (draft: DraggedEventDraft) => {
100
101
  setResources((prev: any) => {
101
- const {event, from, to, resourceId} = draft;
102
+ const {event, from, to, resourceId, date} = draft;
102
103
 
103
104
  return prev.map((res: any) => {
105
+ // ✅ if this is the new target resource
104
106
  if (res.id === resourceId) {
107
+ // was the event originally in a different resource?
105
108
  const wasDifferentResource = event.resourceId !== resourceId;
106
109
 
110
+ // clone event with new times and resourceId
107
111
  const updatedEvent = {
108
112
  ...event,
109
113
  from,
110
114
  to,
111
115
  resourceId,
116
+ date
112
117
  };
113
118
 
114
119
  return {
115
120
  ...res,
116
121
  events: wasDifferentResource
122
+ // if moved from another resource, append it here
117
123
  ? [...res.events, updatedEvent]
124
+ // else update it in place
118
125
  : res.events.map((e: any) => (e.id === event.id ? updatedEvent : e)),
119
126
  };
120
127
  }
121
128
 
129
+ // ✅ if this is the old resource and event moved away
122
130
  if (res.id === event.resourceId && event.resourceId !== resourceId) {
123
131
  return {
124
132
  ...res,
@@ -126,6 +134,7 @@ export default function App() {
126
134
  };
127
135
  }
128
136
 
137
+ // ✅ untouched resources
129
138
  return res;
130
139
  });
131
140
  });
@@ -145,10 +154,17 @@ export default function App() {
145
154
  setNumberOfColumns(randomNumberOfColumns);
146
155
  setLayoutMode(layoutMode === 'stacked' ? 'columns' : 'stacked');
147
156
  }
148
-
157
+
158
+ const addDays = (days: number) => {
159
+ const newDate = new Date(date);
160
+ newDate.setDate(newDate.getDate() + days);
161
+ setDate(newDate);
162
+ };
163
+
149
164
  return (
150
165
  <SafeAreaView style={{backgroundColor: "#fff", flex: 1}} edges={["top"]}>
151
166
  <Calendar
167
+ // mode={'week'}
152
168
  theme={{
153
169
  typography: {
154
170
  fontFamily: 'NunitoSans',
@@ -238,26 +254,28 @@ export default function App() {
238
254
 
239
255
  The `Calendar` component accepts a flexible set of props for customizing layout, theme, and interactivity.
240
256
 
241
- | Prop | Type | Default | Description |
242
- |-----------------------------|------------------------------------------------------------------------------------------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
243
- | **`date`** | `Date` | `new Date()` | The current date displayed in the calendar. |
244
- | **`resources`** | `Array<Resource & { events: Event[]; disabledBlocks?: DisabledBlock[]; disableIntervals?: DisabledInterval[] }>` | **required** | Columns to render. Each resource can provide its own events and optional disabled ranges. |
245
- | **`timezone`** | `string` | device time zone | Time zone used for time labels and taps-to-date conversion. |
246
- | **`startMinutes`** | `number` | `0` (00:00) | Start of the visible timeline in minutes from midnight (e.g. `8 * 60` = 08:00). |
247
- | **`numberOfColumns`** | `number` | `3` | How many resource columns to show side-by-side. |
248
- | **`hourHeight`** | `number` | `120` | Vertical scale: pixels used to render 1 hour. (Affects scrolling/snapping.) |
249
- | **`snapIntervalInMinutes`** | `number` | `5` | Drag/resize snapping granularity in minutes. |
250
- | **`overLappingLayoutMode`** | `LayoutMode` (`'stacked' \| 'columns'`) | `'stacked'` | Strategy for laying out overlapping events within a column. |
251
- | **`theme`** | `CalendarTheme` | | Theme overrides (typography). |
252
- | **`eventSlots`** | `EventSlots` | — | Slot renderers to customize event content. (Common keys: `Body`, `TopRight`.) Example: `{ Body: ({event}) => <MyBody event={event} /> }`. |
253
- | **`eventStyleOverrides`** | `StyleOverrides \| ((event: Event) => StyleOverrides \| undefined)` | — | Per-event styling override (e.g., background, border, radius). Function form lets you style by event. |
254
- | **`isEventSelected`** | `(event: Event) => boolean` | `() => false` | Tell the calendar which events are currently selected. |
255
- | **`isEventDisabled`** | `(event: Event) => boolean` | `() => false` | Mark events as disabled (non-interactive). |
256
- | **`onResourcePress`** | `(resource: Resource) => void` | | Fired when a resource header is pressed. |
257
- | **`onBlockLongPress`** | `(resource: Resource, date: Date) => void` | — | Fired when the user long-presses an empty time block in a column. |
258
- | **`onDisabledBlockPress`** | `(block: DisabledBlock) => void` | — | Fired when a disabled block (e.g., lunch) is tapped. |
259
- | **`onEventPress`** | `(event: Event) => void` | — | Fired when an event is tapped. |
260
- | **`onEventLongPress`** | `(event: Event) => void` | — | Fired when an event is long-pressed. (The calendar also prepares internal drag state at this time.) |
257
+ | Prop | Type | Default | Description |
258
+ |-----------------------------|------------------------------------------------------------------------------------------------------------------|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
259
+ | **`date`** | `Date` | `new Date()` | The anchor day shown in the timeline. In multi-day modes this is the **first** visible day. |
260
+ | **`mode`** | `CalendarMode` (`'day' \| '3days' \| 'week'`) | `'day'` | Controls the column semantics. **day** = many resources for one day. **3days/week** = several days for one resource. |
261
+ | **`activeResourceId`** | `number` | first `resources[0].id` | When `mode !== 'day'`, columns represent days for **this** resource. |
262
+ | **`resources`** | `Array<Resource & { events: Event[]; disabledBlocks?: DisabledBlock[]; disableIntervals?: DisabledInterval[] }>` | **required** | Resource columns. Each resource includes its day’s `events`, optional `disabledBlocks` (finite ranges), and `disableIntervals` (open/recurring ranges). |
263
+ | **`timezone`** | `string` | device time zone | Used for time labels and converting block taps to a `Date`. |
264
+ | **`startMinutes`** | `number` | `0` | Start of visible timeline in minutes after midnight (e.g. `8 * 60` = 08:00). |
265
+ | **`numberOfColumns`** | `number` | `3` | **Day mode only.** How many resource columns to show side-by-side. (In multi-day modes, the column count is fixed by the mode: 3 or 7.) |
266
+ | **`hourHeight`** | `number` | `120` | Vertical density, px per hour. Affects drag/resize and scroll snap. |
267
+ | **`snapIntervalInMinutes`** | `number` | `5` | Drag/resize snapping granularity (in minutes). |
268
+ | **`overLappingLayoutMode`** | `LayoutMode` (`'stacked' \| 'columns'`) | `'stacked'` | Strategy to lay out overlapping events inside a column. |
269
+ | **`theme`** | `CalendarTheme` | — | Typography & palette overrides. |
270
+ | **`eventSlots`** | `EventSlots` | — | Slot renderers to customize event content (e.g. `{ Body, TopRight }`). |
271
+ | **`eventStyleOverrides`** | `StyleOverrides \| ((event: Event) => StyleOverrides \| undefined)` | — | Per-event style override (object or function). |
272
+ | **`isEventSelected`** | `(event: Event) => boolean` | `() => false` | Marks which events are currently selected. |
273
+ | **`isEventDisabled`** | `(event: Event) => boolean` | `() => false` | Marks events as disabled (non-interactive). |
274
+ | **`onResourcePress`** | `(resource: Resource) => void` | — | Invoked when a resource header is pressed. |
275
+ | **`onBlockLongPress`** | `(resource: Resource, date: Date) => void` | — | Long-press on an empty block (grid). |
276
+ | **`onDisabledBlockPress`** | `(block: DisabledBlock) => void` | — | Tap on a disabled block (e.g., lunch). |
277
+ | **`onEventPress`** | `(event: Event) => void` | — | Tap on an event. |
278
+ | **`onEventLongPress`** | `(event: Event) => void` | — | Long-press on an event. The calendar also preps internal drag state here. |
261
279
 
262
280
  ---
263
281
 
@@ -269,6 +287,7 @@ type ResourceId = number;
269
287
  type Event = {
270
288
  id: number;
271
289
  resourceId: ResourceId;
290
+ date: string; // 'yyyy-MM-dd' eg. '2025-11-09'
272
291
  from: number;
273
292
  to: number;
274
293
  title?: string;
@@ -281,6 +300,7 @@ type Event = {
281
300
  type DisabledBlock = {
282
301
  id: number;
283
302
  resourceId: ResourceId;
303
+ date: string; // 'yyyy-MM-dd' eg. '2025-11-09'
284
304
  from: number;
285
305
  to: number;
286
306
  title?: string;
@@ -288,6 +308,7 @@ type DisabledBlock = {
288
308
 
289
309
  type DisabledInterval = {
290
310
  resourceId: ResourceId;
311
+ date: string; // 'yyyy-MM-dd' eg. '2025-11-09'
291
312
  from: number;
292
313
  to: number;
293
314
  };
@@ -300,6 +321,7 @@ type Resource = {
300
321
 
301
322
  type DraggedEventDraft = {
302
323
  event: Event,
324
+ date: string; // 'yyyy-MM-dd' eg. '2025-11-09'
303
325
  from: number,
304
326
  to: number,
305
327
  resourceId: ResourceId
@@ -310,6 +332,8 @@ type CalendarTheme = {
310
332
  fontFamily?: string;
311
333
  };
312
334
  };
335
+
336
+ type CalendarMode = 'day' | '3days' | 'week';
313
337
  ```
314
338
 
315
339
  ---
package/dist/index.d.mts CHANGED
@@ -35,8 +35,8 @@ type Resource = {
35
35
  };
36
36
  type DraggedEventDraft = {
37
37
  event: Event;
38
- from: number;
39
38
  date: string;
39
+ from: number;
40
40
  to: number;
41
41
  resourceId: ResourceId;
42
42
  };
@@ -129,4 +129,4 @@ declare const CalendarBindingProvider: React$1.FC<{
129
129
  children: React$1.ReactNode;
130
130
  }>;
131
131
 
132
- export { Calendar, CalendarBindingProvider, type CalendarTheme, type DisabledBlock, type DisabledInterval, type DraggedEventDraft, type Event, type EventRenderContext, type LayoutMode, type Resource, useCalendarBinding };
132
+ export { Calendar, CalendarBindingProvider, type CalendarMode, type CalendarTheme, type DisabledBlock, type DisabledInterval, type DraggedEventDraft, type Event, type EventRenderContext, type LayoutMode, type Resource, useCalendarBinding };
package/dist/index.d.ts CHANGED
@@ -35,8 +35,8 @@ type Resource = {
35
35
  };
36
36
  type DraggedEventDraft = {
37
37
  event: Event;
38
- from: number;
39
38
  date: string;
39
+ from: number;
40
40
  to: number;
41
41
  resourceId: ResourceId;
42
42
  };
@@ -129,4 +129,4 @@ declare const CalendarBindingProvider: React$1.FC<{
129
129
  children: React$1.ReactNode;
130
130
  }>;
131
131
 
132
- export { Calendar, CalendarBindingProvider, type CalendarTheme, type DisabledBlock, type DisabledInterval, type DraggedEventDraft, type Event, type EventRenderContext, type LayoutMode, type Resource, useCalendarBinding };
132
+ export { Calendar, CalendarBindingProvider, type CalendarMode, type CalendarTheme, type DisabledBlock, type DisabledInterval, type DraggedEventDraft, type Event, type EventRenderContext, type LayoutMode, type Resource, useCalendarBinding };
package/dist/index.js CHANGED
@@ -1455,6 +1455,9 @@ var CalendarInner = (props) => {
1455
1455
  setDraggedEventDraft(null);
1456
1456
  }
1457
1457
  }, [selectedEvent]);
1458
+ React19.useEffect(() => {
1459
+ scrollX.value = 0;
1460
+ }, [mode]);
1458
1461
  const verticalScrollViewRef = Animated2.useAnimatedRef();
1459
1462
  const headerScrollViewRef = Animated2.useAnimatedRef();
1460
1463
  const flashListRef = React19.useRef(null);