react-native-resource-calendar 1.0.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 +21 -0
- package/README.md +341 -0
- package/dist/index.d.mts +123 -0
- package/dist/index.d.ts +123 -0
- package/dist/index.js +1739 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1711 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Wei Chen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# đī¸ react-native-resource-calendar
|
|
2
|
+
|
|
3
|
+
A flexible, performant, and themeable React Native calendar for scheduling apps â built with Zustand, Reanimated, and
|
|
4
|
+
Expo compatibility.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## ⨠Features
|
|
9
|
+
|
|
10
|
+
- â
Multi-resource timeline layout
|
|
11
|
+
- đ¨ Customizable event slots (Body, TopRight)
|
|
12
|
+
- đą Smooth Reanimated drag-and-drop
|
|
13
|
+
- â° Timezone-aware time labels
|
|
14
|
+
- đ§Š Modular store (Zustand binding by default)
|
|
15
|
+
- đī¸ Theme support (font families, weights)
|
|
16
|
+
- đĒļ Lightweight and Expo-ready
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## đĻ Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install react-native-resource-calendar
|
|
24
|
+
# or
|
|
25
|
+
yarn add react-native-resource-calendar
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## đ Quick Start
|
|
29
|
+
|
|
30
|
+
Follow these steps to get started quickly with **React Native Resource Calendar**.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
### 1ī¸âŖ Wrap your app with CalendarBindingProvider
|
|
35
|
+
|
|
36
|
+
### 2ī¸âŖ Feed the Calendar component with resources and events
|
|
37
|
+
|
|
38
|
+
### 3ī¸âŖ Use hooks from useCalendarBinding to interact with the calendar state
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import React from 'react';
|
|
42
|
+
import {Button, StyleSheet, View} from 'react-native';
|
|
43
|
+
import {Calendar, DraggedEventDraft, useCalendarBinding} from "react-native-resource-calendar";
|
|
44
|
+
|
|
45
|
+
const resourceData = [
|
|
46
|
+
{
|
|
47
|
+
id: 1,
|
|
48
|
+
name: "Alice Johnson",
|
|
49
|
+
avatar: "https://randomuser.me/api/portraits/women/11.jpg",
|
|
50
|
+
events: [
|
|
51
|
+
{
|
|
52
|
+
id: 101,
|
|
53
|
+
resourceId: 1,
|
|
54
|
+
from: 8 * 60, // 8:00 AM
|
|
55
|
+
to: 9 * 60, // 9:00 AM
|
|
56
|
+
title: "Physical Therapy",
|
|
57
|
+
description: "Post-surgery recovery session",
|
|
58
|
+
meta: {client: "John Doe"},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 102,
|
|
62
|
+
resourceId: 1,
|
|
63
|
+
from: 10 * 60,
|
|
64
|
+
to: 11 * 60,
|
|
65
|
+
title: "Mobility Assessment",
|
|
66
|
+
description: "Initial consultation",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
disabledBlocks: [
|
|
70
|
+
{
|
|
71
|
+
id: 1001,
|
|
72
|
+
resourceId: 1,
|
|
73
|
+
from: 12 * 60, // 12:00 PM
|
|
74
|
+
to: 13 * 60, // 1:00 PM
|
|
75
|
+
title: "Lunch Break",
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
disableIntervals: [
|
|
79
|
+
{
|
|
80
|
+
resourceId: 1,
|
|
81
|
+
from: 17 * 60, // 5:00 PM
|
|
82
|
+
to: 24 * 60, // 12:00 AM
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 2,
|
|
88
|
+
name: "Bob Martinez",
|
|
89
|
+
avatar: "https://randomuser.me/api/portraits/men/22.jpg",
|
|
90
|
+
events: [
|
|
91
|
+
{
|
|
92
|
+
id: 201,
|
|
93
|
+
resourceId: 2,
|
|
94
|
+
from: 9 * 60 + 30, // 9:30 AM
|
|
95
|
+
to: 10 * 60 + 30, // 10:30 AM
|
|
96
|
+
title: "Personal Training",
|
|
97
|
+
meta: {client: "Alex Kim"},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 202,
|
|
101
|
+
resourceId: 2,
|
|
102
|
+
from: 15 * 60,
|
|
103
|
+
to: 16 * 60,
|
|
104
|
+
title: "Endurance Coaching",
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
disabledBlocks: [
|
|
108
|
+
{
|
|
109
|
+
id: 2001,
|
|
110
|
+
resourceId: 2,
|
|
111
|
+
from: 13 * 60,
|
|
112
|
+
to: 14 * 60,
|
|
113
|
+
title: "Staff Meeting",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
disableIntervals: [
|
|
117
|
+
{
|
|
118
|
+
resourceId: 2,
|
|
119
|
+
from: 7 * 60,
|
|
120
|
+
to: 8 * 60,
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: 3,
|
|
126
|
+
name: "Charlie Kim",
|
|
127
|
+
avatar: "https://randomuser.me/api/portraits/men/33.jpg",
|
|
128
|
+
events: [
|
|
129
|
+
{
|
|
130
|
+
id: 301,
|
|
131
|
+
resourceId: 3,
|
|
132
|
+
from: 11 * 60,
|
|
133
|
+
to: 12 * 60,
|
|
134
|
+
title: "Sports Massage",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: 302,
|
|
138
|
+
resourceId: 3,
|
|
139
|
+
from: 14 * 60 + 15,
|
|
140
|
+
to: 15 * 60,
|
|
141
|
+
title: "Deep Tissue Massage",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
disabledBlocks: [
|
|
145
|
+
{
|
|
146
|
+
id: 3001,
|
|
147
|
+
resourceId: 3,
|
|
148
|
+
from: 12 * 60,
|
|
149
|
+
to: 13 * 60,
|
|
150
|
+
title: "Lunch",
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 4,
|
|
156
|
+
name: "Diana Ross",
|
|
157
|
+
avatar: "https://randomuser.me/api/portraits/women/44.jpg",
|
|
158
|
+
events: [
|
|
159
|
+
{
|
|
160
|
+
id: 401,
|
|
161
|
+
resourceId: 4,
|
|
162
|
+
from: 13 * 60,
|
|
163
|
+
to: 14 * 60,
|
|
164
|
+
title: "Nutrition Plan Review",
|
|
165
|
+
description: "Discuss dietary adjustments",
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
disableIntervals: [
|
|
169
|
+
{
|
|
170
|
+
resourceId: 4,
|
|
171
|
+
from: 18 * 60,
|
|
172
|
+
to: 24 * 60,
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
export default function App() {
|
|
179
|
+
const {
|
|
180
|
+
useGetSelectedEvent,
|
|
181
|
+
useSetSelectedEvent,
|
|
182
|
+
useGetDraggedEventDraft
|
|
183
|
+
} = useCalendarBinding();
|
|
184
|
+
const selectedEvent = useGetSelectedEvent();
|
|
185
|
+
const setSelectedEvent = useSetSelectedEvent();
|
|
186
|
+
const draggedEventDraft = useGetDraggedEventDraft();
|
|
187
|
+
const [date, setDate] = React.useState(new Date());
|
|
188
|
+
const [resources, setResources] = React.useState(resourceData)
|
|
189
|
+
|
|
190
|
+
const updateResourcesOnDrag = React.useCallback(
|
|
191
|
+
(draft: DraggedEventDraft) => {
|
|
192
|
+
setResources((prev: any) => {
|
|
193
|
+
const {event, from, to, resourceId} = draft;
|
|
194
|
+
|
|
195
|
+
return prev.map((res: any) => {
|
|
196
|
+
if (res.id === resourceId) {
|
|
197
|
+
const wasDifferentResource = event.resourceId !== resourceId;
|
|
198
|
+
|
|
199
|
+
const updatedEvent = {
|
|
200
|
+
...event,
|
|
201
|
+
from,
|
|
202
|
+
to,
|
|
203
|
+
resourceId,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
...res,
|
|
208
|
+
events: wasDifferentResource
|
|
209
|
+
? [...res.events, updatedEvent]
|
|
210
|
+
: res.events.map((e: any) => (e.id === event.id ? updatedEvent : e)),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (res.id === event.resourceId && event.resourceId !== resourceId) {
|
|
215
|
+
return {
|
|
216
|
+
...res,
|
|
217
|
+
events: res.events.filter((e: any) => e.id !== event.id),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return res;
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
},
|
|
225
|
+
[setResources]
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<CalendarBindingProvider>
|
|
230
|
+
<View style={{flex: 1}}>
|
|
231
|
+
<Calendar
|
|
232
|
+
resources={resources}
|
|
233
|
+
date={date}
|
|
234
|
+
startMinutes={8 * 60}
|
|
235
|
+
numberOfColumns={3}
|
|
236
|
+
/>
|
|
237
|
+
{
|
|
238
|
+
selectedEvent && <View style={{
|
|
239
|
+
flexDirection: 'row',
|
|
240
|
+
justifyContent: 'space-between'
|
|
241
|
+
}}>
|
|
242
|
+
<Button
|
|
243
|
+
title="Cancel"
|
|
244
|
+
onPress={() => {
|
|
245
|
+
setSelectedEvent(null);
|
|
246
|
+
}}
|
|
247
|
+
/>
|
|
248
|
+
<Button
|
|
249
|
+
title="Save"
|
|
250
|
+
onPress={() => {
|
|
251
|
+
if (draggedEventDraft) {
|
|
252
|
+
updateResourcesOnDrag(draggedEventDraft!);
|
|
253
|
+
}
|
|
254
|
+
setSelectedEvent(null);
|
|
255
|
+
}}
|
|
256
|
+
/>
|
|
257
|
+
</View>
|
|
258
|
+
}
|
|
259
|
+
</View>
|
|
260
|
+
</CalendarBindingProvider>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## âī¸ Calendar Props
|
|
266
|
+
|
|
267
|
+
The `Calendar` component accepts a flexible set of props for customizing layout, theme, and interactivity.
|
|
268
|
+
|
|
269
|
+
| Prop | Type | Default | Description |
|
|
270
|
+
|-----------------------------|------------------------------------------------------------------------------------------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
|
|
271
|
+
| **`date`** | `Date` | `new Date()` | The current date displayed in the calendar. |
|
|
272
|
+
| **`resources`** | `Array<Resource & { events: Event[]; disabledBlocks?: DisabledBlock[]; disableIntervals?: DisabledInterval[] }>` | **required** | Columns to render. Each resource can provide its own events and optional disabled ranges. |
|
|
273
|
+
| **`timezone`** | `string` | device time zone | Time zone used for time labels and taps-to-date conversion. |
|
|
274
|
+
| **`startMinutes`** | `number` | `0` (00:00) | Start of the visible timeline in minutes from midnight (e.g. `8 * 60` = 08:00). |
|
|
275
|
+
| **`numberOfColumns`** | `number` | `3` | How many resource columns to show side-by-side. |
|
|
276
|
+
| **`hourHeight`** | `number` | `120` | Vertical scale: pixels used to render 1 hour. (Affects scrolling/snapping.) |
|
|
277
|
+
| **`snapIntervalInMinutes`** | `number` | `5` | Drag/resize snapping granularity in minutes. |
|
|
278
|
+
| **`overLappingLayoutMode`** | `LayoutMode` (`'stacked' \| 'columns'`) | `'stacked'` | Strategy for laying out overlapping events within a column. |
|
|
279
|
+
| **`theme`** | `CalendarTheme` | â | Theme overrides (typography). |
|
|
280
|
+
| **`eventSlots`** | `EventSlots` | â | Slot renderers to customize event content. (Common keys: `Body`, `TopRight`.) Example: `{ Body: ({event}) => <MyBody event={event} /> }`. |
|
|
281
|
+
| **`eventStyleOverrides`** | `StyleOverrides \| ((event: Event) => StyleOverrides \| undefined)` | â | Per-event styling override (e.g., background, border, radius). Function form lets you style by event. |
|
|
282
|
+
| **`isEventSelected`** | `(event: Event) => boolean` | `() => false` | Tell the calendar which events are currently selected. |
|
|
283
|
+
| **`isEventDisabled`** | `(event: Event) => boolean` | `() => false` | Mark events as disabled (non-interactive). |
|
|
284
|
+
| **`onResourcePress`** | `(resource: Resource) => void` | â | Fired when a resource header is pressed. |
|
|
285
|
+
| **`onBlockLongPress`** | `(resource: Resource, date: Date) => void` | â | Fired when the user long-presses an empty time block in a column. |
|
|
286
|
+
| **`onDisabledBlockPress`** | `(block: DisabledBlock) => void` | â | Fired when a disabled block (e.g., lunch) is tapped. |
|
|
287
|
+
| **`onEventPress`** | `(event: Event) => void` | â | Fired when an event is tapped. |
|
|
288
|
+
| **`onEventLongPress`** | `(event: Event) => void` | â | Fired when an event is long-pressed. (The calendar also prepares internal drag state at this time.) |
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### đ§Š Related Types
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
type ResourceId = number;
|
|
296
|
+
|
|
297
|
+
type Event = {
|
|
298
|
+
id: number;
|
|
299
|
+
resourceId: ResourceId;
|
|
300
|
+
from: number;
|
|
301
|
+
to: number;
|
|
302
|
+
title?: string;
|
|
303
|
+
description?: string;
|
|
304
|
+
meta?: {
|
|
305
|
+
[key: string]: any;
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
type DisabledBlock = {
|
|
310
|
+
id: number;
|
|
311
|
+
resourceId: ResourceId;
|
|
312
|
+
from: number;
|
|
313
|
+
to: number;
|
|
314
|
+
title?: string;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
type DisabledInterval = {
|
|
318
|
+
resourceId: ResourceId;
|
|
319
|
+
from: number;
|
|
320
|
+
to: number;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
type Resource = {
|
|
324
|
+
id: ResourceId;
|
|
325
|
+
name: string;
|
|
326
|
+
avatar?: string;
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
type DraggedEventDraft = {
|
|
330
|
+
event: Event,
|
|
331
|
+
from: number,
|
|
332
|
+
to: number,
|
|
333
|
+
resourceId: ResourceId
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
type CalendarTheme = {
|
|
337
|
+
typography?: {
|
|
338
|
+
fontFamily?: string;
|
|
339
|
+
};
|
|
340
|
+
};
|
|
341
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React$1 from 'react';
|
|
2
|
+
import { ViewStyle, TextStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type ResourceId = number;
|
|
5
|
+
type Event = {
|
|
6
|
+
id: number;
|
|
7
|
+
resourceId: ResourceId;
|
|
8
|
+
from: number;
|
|
9
|
+
to: number;
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
meta?: {
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
type DisabledBlock = {
|
|
17
|
+
id: number;
|
|
18
|
+
resourceId: ResourceId;
|
|
19
|
+
from: number;
|
|
20
|
+
to: number;
|
|
21
|
+
title?: string;
|
|
22
|
+
};
|
|
23
|
+
type DisabledInterval = {
|
|
24
|
+
resourceId: ResourceId;
|
|
25
|
+
from: number;
|
|
26
|
+
to: number;
|
|
27
|
+
};
|
|
28
|
+
type Resource = {
|
|
29
|
+
id: ResourceId;
|
|
30
|
+
name: string;
|
|
31
|
+
avatar?: string;
|
|
32
|
+
};
|
|
33
|
+
type DraggedEventDraft = {
|
|
34
|
+
event: Event;
|
|
35
|
+
from: number;
|
|
36
|
+
to: number;
|
|
37
|
+
resourceId: ResourceId;
|
|
38
|
+
};
|
|
39
|
+
type CalendarTheme = {
|
|
40
|
+
typography?: {
|
|
41
|
+
/** Expo-registered font name */
|
|
42
|
+
fontFamily?: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type LayoutMode = "columns" | "stacked";
|
|
47
|
+
|
|
48
|
+
type EventRenderContext = {
|
|
49
|
+
hourHeight: number;
|
|
50
|
+
};
|
|
51
|
+
type EventSlots = {
|
|
52
|
+
TopRight?: React$1.ComponentType<{
|
|
53
|
+
event: Event;
|
|
54
|
+
ctx: EventRenderContext;
|
|
55
|
+
}>;
|
|
56
|
+
Body?: React$1.ComponentType<{
|
|
57
|
+
event: Event;
|
|
58
|
+
ctx: EventRenderContext;
|
|
59
|
+
}>;
|
|
60
|
+
};
|
|
61
|
+
type StyleOverrides = Partial<{
|
|
62
|
+
container: ViewStyle;
|
|
63
|
+
content: ViewStyle;
|
|
64
|
+
title: TextStyle;
|
|
65
|
+
desc: TextStyle;
|
|
66
|
+
}>;
|
|
67
|
+
|
|
68
|
+
type FlagFn = (event: Event) => boolean;
|
|
69
|
+
interface CalendarProps {
|
|
70
|
+
timezone?: string;
|
|
71
|
+
date: Date;
|
|
72
|
+
startMinutes?: number;
|
|
73
|
+
resources: Array<Resource & {
|
|
74
|
+
events: Event[];
|
|
75
|
+
disabledBlocks?: DisabledBlock[];
|
|
76
|
+
disableIntervals?: DisabledInterval[];
|
|
77
|
+
}>;
|
|
78
|
+
snapIntervalInMinutes?: number;
|
|
79
|
+
numberOfColumns?: number;
|
|
80
|
+
hourHeight?: number;
|
|
81
|
+
onResourcePress?: (resource: Resource) => void;
|
|
82
|
+
onBlockLongPress?: (resource: Resource, date: Date) => void;
|
|
83
|
+
onDisabledBlockPress?: (block: DisabledBlock) => void;
|
|
84
|
+
onEventPress?: (event: Event) => void;
|
|
85
|
+
onEventLongPress?: (event: Event) => void;
|
|
86
|
+
eventSlots?: EventSlots;
|
|
87
|
+
eventStyleOverrides?: StyleOverrides | ((event: Event) => StyleOverrides | undefined);
|
|
88
|
+
isEventSelected?: FlagFn;
|
|
89
|
+
isEventDisabled?: FlagFn;
|
|
90
|
+
theme?: CalendarTheme;
|
|
91
|
+
overLappingLayoutMode?: LayoutMode;
|
|
92
|
+
}
|
|
93
|
+
declare const Calendar: React$1.FC<CalendarProps>;
|
|
94
|
+
|
|
95
|
+
type SetDayDataPayload = {
|
|
96
|
+
events?: Record<ResourceId, Event[]>;
|
|
97
|
+
disabledBlocks?: Record<ResourceId, DisabledBlock[]>;
|
|
98
|
+
disableIntervals?: Record<ResourceId, DisabledInterval[]>;
|
|
99
|
+
};
|
|
100
|
+
type CalendarStoreBinding = {
|
|
101
|
+
/** Instance-scoped provider (no globals). */
|
|
102
|
+
Provider: React.FC<{
|
|
103
|
+
children: React.ReactNode;
|
|
104
|
+
}>;
|
|
105
|
+
useResourceById: (id: ResourceId) => Resource;
|
|
106
|
+
useEventsFor: (resourceId: ResourceId) => ReadonlyArray<Event>;
|
|
107
|
+
useDisabledBlocksFor: (resourceId: ResourceId) => ReadonlyArray<DisabledBlock>;
|
|
108
|
+
useDisabledIntervalsFor: (resourceId: ResourceId) => ReadonlyArray<DisabledInterval>;
|
|
109
|
+
useUpsertResources: () => (rs: Array<Pick<Resource, 'id' | 'name' | 'avatar'>>) => void;
|
|
110
|
+
useSetDayData: () => (payload: SetDayDataPayload) => void;
|
|
111
|
+
useGetSelectedEvent: () => Event | null;
|
|
112
|
+
useSetSelectedEvent: () => (ev: Event | null) => void;
|
|
113
|
+
useGetDraggedEventDraft: () => DraggedEventDraft | null;
|
|
114
|
+
useSetDraggedEventDraft: () => (draft: DraggedEventDraft | null) => void;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
declare const useCalendarBinding: () => CalendarStoreBinding;
|
|
118
|
+
declare const CalendarBindingProvider: React$1.FC<{
|
|
119
|
+
binding?: CalendarStoreBinding;
|
|
120
|
+
children: React$1.ReactNode;
|
|
121
|
+
}>;
|
|
122
|
+
|
|
123
|
+
export { Calendar, CalendarBindingProvider, type CalendarTheme, type DisabledBlock, type DisabledInterval, type DraggedEventDraft, type Event, type Resource, useCalendarBinding };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React$1 from 'react';
|
|
2
|
+
import { ViewStyle, TextStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type ResourceId = number;
|
|
5
|
+
type Event = {
|
|
6
|
+
id: number;
|
|
7
|
+
resourceId: ResourceId;
|
|
8
|
+
from: number;
|
|
9
|
+
to: number;
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
meta?: {
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
type DisabledBlock = {
|
|
17
|
+
id: number;
|
|
18
|
+
resourceId: ResourceId;
|
|
19
|
+
from: number;
|
|
20
|
+
to: number;
|
|
21
|
+
title?: string;
|
|
22
|
+
};
|
|
23
|
+
type DisabledInterval = {
|
|
24
|
+
resourceId: ResourceId;
|
|
25
|
+
from: number;
|
|
26
|
+
to: number;
|
|
27
|
+
};
|
|
28
|
+
type Resource = {
|
|
29
|
+
id: ResourceId;
|
|
30
|
+
name: string;
|
|
31
|
+
avatar?: string;
|
|
32
|
+
};
|
|
33
|
+
type DraggedEventDraft = {
|
|
34
|
+
event: Event;
|
|
35
|
+
from: number;
|
|
36
|
+
to: number;
|
|
37
|
+
resourceId: ResourceId;
|
|
38
|
+
};
|
|
39
|
+
type CalendarTheme = {
|
|
40
|
+
typography?: {
|
|
41
|
+
/** Expo-registered font name */
|
|
42
|
+
fontFamily?: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type LayoutMode = "columns" | "stacked";
|
|
47
|
+
|
|
48
|
+
type EventRenderContext = {
|
|
49
|
+
hourHeight: number;
|
|
50
|
+
};
|
|
51
|
+
type EventSlots = {
|
|
52
|
+
TopRight?: React$1.ComponentType<{
|
|
53
|
+
event: Event;
|
|
54
|
+
ctx: EventRenderContext;
|
|
55
|
+
}>;
|
|
56
|
+
Body?: React$1.ComponentType<{
|
|
57
|
+
event: Event;
|
|
58
|
+
ctx: EventRenderContext;
|
|
59
|
+
}>;
|
|
60
|
+
};
|
|
61
|
+
type StyleOverrides = Partial<{
|
|
62
|
+
container: ViewStyle;
|
|
63
|
+
content: ViewStyle;
|
|
64
|
+
title: TextStyle;
|
|
65
|
+
desc: TextStyle;
|
|
66
|
+
}>;
|
|
67
|
+
|
|
68
|
+
type FlagFn = (event: Event) => boolean;
|
|
69
|
+
interface CalendarProps {
|
|
70
|
+
timezone?: string;
|
|
71
|
+
date: Date;
|
|
72
|
+
startMinutes?: number;
|
|
73
|
+
resources: Array<Resource & {
|
|
74
|
+
events: Event[];
|
|
75
|
+
disabledBlocks?: DisabledBlock[];
|
|
76
|
+
disableIntervals?: DisabledInterval[];
|
|
77
|
+
}>;
|
|
78
|
+
snapIntervalInMinutes?: number;
|
|
79
|
+
numberOfColumns?: number;
|
|
80
|
+
hourHeight?: number;
|
|
81
|
+
onResourcePress?: (resource: Resource) => void;
|
|
82
|
+
onBlockLongPress?: (resource: Resource, date: Date) => void;
|
|
83
|
+
onDisabledBlockPress?: (block: DisabledBlock) => void;
|
|
84
|
+
onEventPress?: (event: Event) => void;
|
|
85
|
+
onEventLongPress?: (event: Event) => void;
|
|
86
|
+
eventSlots?: EventSlots;
|
|
87
|
+
eventStyleOverrides?: StyleOverrides | ((event: Event) => StyleOverrides | undefined);
|
|
88
|
+
isEventSelected?: FlagFn;
|
|
89
|
+
isEventDisabled?: FlagFn;
|
|
90
|
+
theme?: CalendarTheme;
|
|
91
|
+
overLappingLayoutMode?: LayoutMode;
|
|
92
|
+
}
|
|
93
|
+
declare const Calendar: React$1.FC<CalendarProps>;
|
|
94
|
+
|
|
95
|
+
type SetDayDataPayload = {
|
|
96
|
+
events?: Record<ResourceId, Event[]>;
|
|
97
|
+
disabledBlocks?: Record<ResourceId, DisabledBlock[]>;
|
|
98
|
+
disableIntervals?: Record<ResourceId, DisabledInterval[]>;
|
|
99
|
+
};
|
|
100
|
+
type CalendarStoreBinding = {
|
|
101
|
+
/** Instance-scoped provider (no globals). */
|
|
102
|
+
Provider: React.FC<{
|
|
103
|
+
children: React.ReactNode;
|
|
104
|
+
}>;
|
|
105
|
+
useResourceById: (id: ResourceId) => Resource;
|
|
106
|
+
useEventsFor: (resourceId: ResourceId) => ReadonlyArray<Event>;
|
|
107
|
+
useDisabledBlocksFor: (resourceId: ResourceId) => ReadonlyArray<DisabledBlock>;
|
|
108
|
+
useDisabledIntervalsFor: (resourceId: ResourceId) => ReadonlyArray<DisabledInterval>;
|
|
109
|
+
useUpsertResources: () => (rs: Array<Pick<Resource, 'id' | 'name' | 'avatar'>>) => void;
|
|
110
|
+
useSetDayData: () => (payload: SetDayDataPayload) => void;
|
|
111
|
+
useGetSelectedEvent: () => Event | null;
|
|
112
|
+
useSetSelectedEvent: () => (ev: Event | null) => void;
|
|
113
|
+
useGetDraggedEventDraft: () => DraggedEventDraft | null;
|
|
114
|
+
useSetDraggedEventDraft: () => (draft: DraggedEventDraft | null) => void;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
declare const useCalendarBinding: () => CalendarStoreBinding;
|
|
118
|
+
declare const CalendarBindingProvider: React$1.FC<{
|
|
119
|
+
binding?: CalendarStoreBinding;
|
|
120
|
+
children: React$1.ReactNode;
|
|
121
|
+
}>;
|
|
122
|
+
|
|
123
|
+
export { Calendar, CalendarBindingProvider, type CalendarTheme, type DisabledBlock, type DisabledInterval, type DraggedEventDraft, type Event, type Resource, useCalendarBinding };
|