react-native-bigger-calendar 0.1.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/README.md +182 -0
- package/dist/index.d.mts +302 -0
- package/dist/index.d.ts +302 -0
- package/dist/index.js +930 -0
- package/dist/index.mjs +891 -0
- package/package.json +75 -0
- package/src/components/Calendar.tsx +147 -0
- package/src/components/DefaultEvent.tsx +57 -0
- package/src/components/MonthPager.tsx +165 -0
- package/src/components/MonthView.tsx +178 -0
- package/src/components/TimeGrid.tsx +825 -0
- package/src/index.tsx +30 -0
- package/src/theme.ts +94 -0
- package/src/types.ts +56 -0
- package/src/utils/dates.ts +20 -0
- package/src/utils/layout.ts +119 -0
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# react-native-bigger-calendar
|
|
2
|
+
|
|
3
|
+
A generic, themeable **month / week / day** calendar for React Native.
|
|
4
|
+
|
|
5
|
+
- π Three views β month grid, week and day time-grids
|
|
6
|
+
- π€ Pinch-to-zoom on the week/day grid (UI thread, no re-renders)
|
|
7
|
+
- βΎοΈ Virtualized, snap-paging months/weeks/days via [`@legendapp/list`](https://legendapp.com/open-source/list/)
|
|
8
|
+
- π§© Bring-your-own event type (`CalendarEvent<T>`) and a `renderEvent` escape hatch
|
|
9
|
+
- π¨ Fully themeable, with sensible defaults (no styling library required)
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install react-native-bigger-calendar
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Peer dependencies
|
|
18
|
+
|
|
19
|
+
This library relies on the following being installed in your app:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm install react-native-reanimated react-native-gesture-handler @legendapp/list
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Make sure Reanimated and Gesture Handler are set up per their own docs (Babel
|
|
26
|
+
plugin, `GestureHandlerRootView` at the root of your app).
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { useState } from 'react';
|
|
32
|
+
import { Calendar, type CalendarEvent } from 'react-native-bigger-calendar';
|
|
33
|
+
|
|
34
|
+
type MyEvent = { id: string; color: string };
|
|
35
|
+
|
|
36
|
+
const events: CalendarEvent<MyEvent>[] = [
|
|
37
|
+
{
|
|
38
|
+
id: '1',
|
|
39
|
+
color: '#1F6FEB',
|
|
40
|
+
title: 'Lecture',
|
|
41
|
+
start: new Date(2026, 5, 19, 10, 0),
|
|
42
|
+
end: new Date(2026, 5, 19, 11, 30),
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export function MyCalendar() {
|
|
47
|
+
const [mode, setMode] = useState<'month' | 'week' | 'day'>('week');
|
|
48
|
+
const [date, setDate] = useState(new Date());
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Calendar
|
|
52
|
+
mode={mode}
|
|
53
|
+
date={date}
|
|
54
|
+
events={events}
|
|
55
|
+
weekStartsOn={1}
|
|
56
|
+
onChangeDate={setDate}
|
|
57
|
+
onPressEvent={(event) => console.log(event.id)}
|
|
58
|
+
onPressDay={(day) => {
|
|
59
|
+
setDate(day);
|
|
60
|
+
setMode('day');
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Custom events
|
|
68
|
+
|
|
69
|
+
The built-in renderer draws a simple titled box. Pass `renderEvent` β **a React
|
|
70
|
+
component**, not a callback β to take full control. Because it's rendered as a
|
|
71
|
+
component, it may use hooks. On the week/day grid you also receive `boxHeight`, a
|
|
72
|
+
Reanimated shared value tracking the live pixel height of the box (driven by
|
|
73
|
+
pinch-zoom), so you can reveal detail progressively without re-rendering:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
77
|
+
import { Pressable, Text } from 'react-native';
|
|
78
|
+
import type { RenderEventArgs } from 'react-native-bigger-calendar';
|
|
79
|
+
|
|
80
|
+
// Define the component once (don't inline it, or it remounts every render).
|
|
81
|
+
function MyEvent({ event, boxHeight, onPress }: RenderEventArgs<MyEvent>) {
|
|
82
|
+
const detailStyle = useAnimatedStyle(() => ({
|
|
83
|
+
display: (boxHeight?.value ?? Infinity) >= 84 ? 'flex' : 'none',
|
|
84
|
+
}));
|
|
85
|
+
return (
|
|
86
|
+
<Pressable style={{ flex: 1, backgroundColor: event.color }} onPress={onPress}>
|
|
87
|
+
<Text>{event.title}</Text>
|
|
88
|
+
<Animated.View style={detailStyle}>
|
|
89
|
+
<Text>{event.start.toLocaleTimeString()}</Text>
|
|
90
|
+
</Animated.View>
|
|
91
|
+
</Pressable>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
<Calendar /* ... */ renderEvent={MyEvent} />;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Theming
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
<Calendar
|
|
102
|
+
// ...
|
|
103
|
+
theme={{
|
|
104
|
+
colors: { todayBackground: '#E5484D', nowIndicator: '#E5484D' },
|
|
105
|
+
text: { dayNumber: { fontSize: 24, fontWeight: '800' } },
|
|
106
|
+
}}
|
|
107
|
+
/>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
See `CalendarTheme` for the full set of tokens. Anything you omit falls back to
|
|
111
|
+
`defaultTheme`.
|
|
112
|
+
|
|
113
|
+
### Week/day grid options
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
<Calendar
|
|
117
|
+
mode="week"
|
|
118
|
+
// ...
|
|
119
|
+
minHour={7} // window the grid to 07:00β21:00
|
|
120
|
+
maxHour={21}
|
|
121
|
+
ampm // 12-hour hour labels ("7 AM")
|
|
122
|
+
onPressCell={(date) => createEventAt(date)} // tap empty space -> date+time
|
|
123
|
+
/>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- `minHour` / `maxHour` clamp the visible hours (defaults `0` / `24`); events and
|
|
127
|
+
the now-line outside the window are hidden, and the initial scroll is adjusted.
|
|
128
|
+
- `ampm` switches hour labels to 12-hour AM/PM (default 24h).
|
|
129
|
+
- `onPressCell(date)` fires when empty grid space is tapped, with the date+time
|
|
130
|
+
under the touch β handy for "create event". (Event taps still go to `onPressEvent`.)
|
|
131
|
+
- `freeSwipe` (default `false`) controls paging: by default one day/week/month
|
|
132
|
+
moves per swipe; set it to allow a fling to carry across several pages (still
|
|
133
|
+
snapping to a page boundary). Applies to all modes.
|
|
134
|
+
|
|
135
|
+
## Components
|
|
136
|
+
|
|
137
|
+
`<Calendar>` is the batteries-included entry point. The building blocks it wraps
|
|
138
|
+
are also exported for advanced layouts:
|
|
139
|
+
|
|
140
|
+
| Export | Description |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| `Calendar` | Top-level component; switches between month/week/day. |
|
|
143
|
+
| `MonthView` | A single month grid. |
|
|
144
|
+
| `MonthPager` | Horizontally-paged, virtualized months. |
|
|
145
|
+
| `TimeGrid` | Paged, pinch-zoomable week/day time-grid. |
|
|
146
|
+
| `DefaultEvent` | The built-in event renderer. |
|
|
147
|
+
| `useCalendarTheme` | Read the active theme inside a custom renderer. |
|
|
148
|
+
|
|
149
|
+
## Notes & limitations
|
|
150
|
+
|
|
151
|
+
- **Multi-day events** are supported: pass one event and it appears on every day
|
|
152
|
+
it spans. On the week/day grid each day shows the clipped segment (so a
|
|
153
|
+
23:00β01:00 event renders 23:00β24:00, then 00:00β01:00), and `renderEvent`
|
|
154
|
+
receives `continuesBefore`/`continuesAfter` so you can draw continuation hints.
|
|
155
|
+
A dedicated all-day lane (and an explicit `allDay` flag) is not yet provided.
|
|
156
|
+
- **`weekStartsOn` defaults to `0` (Sunday).** Pass `1` for Monday-first.
|
|
157
|
+
- **Controlled `date`.** The calendar is controlled: echo `onChangeDate` back
|
|
158
|
+
into the `date` prop, or paging and the "today" realign won't track.
|
|
159
|
+
- **External `cellHeight`.** If you own `cellHeight`, drive zoom through the
|
|
160
|
+
pinch gesture. Programmatic writes outside a pinch won't propagate to
|
|
161
|
+
off-screen pages until the next gesture settles.
|
|
162
|
+
- **Stable props.** Pass stable `renderEvent`/`keyExtractor`/`on*` references
|
|
163
|
+
(module scope or `useCallback`) so the memoized inner views can skip renders.
|
|
164
|
+
|
|
165
|
+
## Example app
|
|
166
|
+
|
|
167
|
+
A runnable Expo demo lives in [`example/`](./example) β month/week/day modes, a
|
|
168
|
+
multi-day event, drill-into-day on tap, and one-page paging.
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
cd example
|
|
172
|
+
npm install
|
|
173
|
+
npx expo run:ios # or: npx expo run:android
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
It consumes the library straight from `../src` (via the example's
|
|
177
|
+
`metro.config.js`), so edits to the package hot-reload into the demo. A custom
|
|
178
|
+
dev build is required (Reanimated worklets aren't available in Expo Go).
|
|
179
|
+
|
|
180
|
+
## License
|
|
181
|
+
|
|
182
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { ComponentType } from "react";
|
|
2
|
+
import { SharedValue, useSharedValue } from "react-native-reanimated";
|
|
3
|
+
import { TextStyle } from "react-native";
|
|
4
|
+
|
|
5
|
+
//#region src/theme.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* The full set of colours, text styles and metrics the calendar paints with.
|
|
8
|
+
* Supply a `Partial<CalendarTheme>` to `<Calendar theme={...} />`; missing keys
|
|
9
|
+
* fall back to {@link defaultTheme}, so you only override what you care about.
|
|
10
|
+
*/
|
|
11
|
+
interface CalendarTheme {
|
|
12
|
+
colors: {
|
|
13
|
+
/** Hour lines, day separators and month-cell borders. */gridLine: string; /** Background tint behind weekend columns/cells. */
|
|
14
|
+
weekendBackground: string; /** Fill of the "today" badge (and any today highlight). */
|
|
15
|
+
todayBackground: string; /** Text on top of the today badge. */
|
|
16
|
+
todayText: string; /** The current-time indicator line on the week/day grid. */
|
|
17
|
+
nowIndicator: string; /** Default text colour (day numbers, weekday labels). */
|
|
18
|
+
text: string; /** Muted text (hour labels, "+N more"). */
|
|
19
|
+
textMuted: string; /** Dimmed text for days outside the current month. */
|
|
20
|
+
textDisabled: string; /** Background of the built-in default event box. */
|
|
21
|
+
eventBackground: string; /** Text colour inside the built-in default event box. */
|
|
22
|
+
eventText: string;
|
|
23
|
+
};
|
|
24
|
+
text: {
|
|
25
|
+
/** Large day number in the week/day header. */dayNumber: TextStyle; /** Short weekday label ("Mon") in headers. */
|
|
26
|
+
weekday: TextStyle; /** Date number inside a month cell. */
|
|
27
|
+
dateCell: TextStyle; /** Hour labels down the left of the time grid. */
|
|
28
|
+
hourLabel: TextStyle; /** The "+N more" overflow label in month cells. */
|
|
29
|
+
more: TextStyle; /** Title inside the built-in default event box. */
|
|
30
|
+
eventTitle: TextStyle;
|
|
31
|
+
};
|
|
32
|
+
/** Corner radius of the today badge. Use a large value for a circle. */
|
|
33
|
+
todayBadgeRadius: number;
|
|
34
|
+
}
|
|
35
|
+
declare const defaultTheme: CalendarTheme;
|
|
36
|
+
/** Deep-merge a partial theme over {@link defaultTheme}. */
|
|
37
|
+
declare function mergeTheme(theme?: PartialCalendarTheme): CalendarTheme;
|
|
38
|
+
type PartialCalendarTheme = {
|
|
39
|
+
colors?: Partial<CalendarTheme['colors']>;
|
|
40
|
+
text?: Partial<CalendarTheme['text']>;
|
|
41
|
+
todayBadgeRadius?: number;
|
|
42
|
+
};
|
|
43
|
+
declare const CalendarThemeProvider: import("react").Provider<CalendarTheme>;
|
|
44
|
+
declare const useCalendarTheme: () => CalendarTheme;
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/types.d.ts
|
|
47
|
+
type CalendarMode = 'day' | 'week' | 'month';
|
|
48
|
+
/**
|
|
49
|
+
* The minimal shape every calendar event must have. Layout (positioning,
|
|
50
|
+
* overlap resolution, paging) only ever reads `start`/`end`; `title` is used by
|
|
51
|
+
* the built-in default renderer. Anything else lives in your own type and is
|
|
52
|
+
* threaded through untouched via the `T` generic.
|
|
53
|
+
*/
|
|
54
|
+
interface ICalendarEvent {
|
|
55
|
+
start: Date;
|
|
56
|
+
end: Date;
|
|
57
|
+
title?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* An event carrying arbitrary extra fields `T` alongside the required shape.
|
|
61
|
+
* `ICalendarEvent` is authoritative: keys it reserves (`start`/`end`/`title`)
|
|
62
|
+
* cannot be re-typed by `T`.
|
|
63
|
+
*/
|
|
64
|
+
type CalendarEvent<T = unknown> = ICalendarEvent & Omit<T, keyof ICalendarEvent>;
|
|
65
|
+
type RenderEventArgs<T = unknown> = {
|
|
66
|
+
event: CalendarEvent<T>;
|
|
67
|
+
mode: CalendarMode;
|
|
68
|
+
/**
|
|
69
|
+
* Live pixel height of the event box on the week/day grid, driven on the UI
|
|
70
|
+
* thread by pinch-to-zoom. Use it to reveal detail progressively as the box
|
|
71
|
+
* grows. `undefined` in month mode, where events render at a fixed size.
|
|
72
|
+
*/
|
|
73
|
+
boxHeight?: SharedValue<number>;
|
|
74
|
+
/**
|
|
75
|
+
* On the week/day grid, true when this is a clipped segment of a multi-day
|
|
76
|
+
* event that started on an earlier day / continues onto a later day. Lets a
|
|
77
|
+
* renderer draw "continues" affordances. `undefined` in month mode.
|
|
78
|
+
*/
|
|
79
|
+
continuesBefore?: boolean;
|
|
80
|
+
continuesAfter?: boolean;
|
|
81
|
+
onPress: () => void;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* A component that renders a single event. It is rendered as a real component
|
|
85
|
+
* (not called as a function), so it may safely use hooks β including Reanimated
|
|
86
|
+
* hooks driven by `boxHeight`. Render an element that fills its container
|
|
87
|
+
* (`flex: 1`); the calendar positions and sizes the wrapping box for you.
|
|
88
|
+
*/
|
|
89
|
+
type RenderEvent<T = unknown> = ComponentType<RenderEventArgs<T>>;
|
|
90
|
+
/** Build a stable key for an event. Defaults to start-time + index. */
|
|
91
|
+
type EventKeyExtractor<T = unknown> = (event: CalendarEvent<T>, index: number) => string;
|
|
92
|
+
/** Sunday = 0 β¦ Saturday = 6, matching `Date.prototype.getDay()`. */
|
|
93
|
+
type WeekStartsOn = 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/components/Calendar.d.ts
|
|
96
|
+
type CalendarProps<T> = {
|
|
97
|
+
events: CalendarEvent<T>[];
|
|
98
|
+
mode: CalendarMode;
|
|
99
|
+
date: Date;
|
|
100
|
+
onChangeDate: (date: Date) => void;
|
|
101
|
+
onPressEvent: (event: CalendarEvent<T>) => void; /** Tap a day cell (month mode) β e.g. drill into the day view. */
|
|
102
|
+
onPressDay?: (date: Date) => void; /** Tap the "+N more" overflow label in a month cell. */
|
|
103
|
+
onPressMore?: (events: CalendarEvent<T>[], date: Date) => void; /** Tap empty space on the week/day grid; receives the date+time pressed. */
|
|
104
|
+
onPressCell?: (date: Date) => void; /** Max events shown per month cell before they collapse into "+N more". */
|
|
105
|
+
maxVisibleEventCount?: number; /** First day of the week. Sunday = 0 (default) β¦ Saturday = 6. */
|
|
106
|
+
weekStartsOn?: WeekStartsOn; /** Replace the built-in event box. Return a `flex: 1` element. */
|
|
107
|
+
renderEvent?: RenderEvent<T>; /** Stable key per event. Defaults to start-time + index. */
|
|
108
|
+
keyExtractor?: EventKeyExtractor<T>; /** Partial theme merged over the defaults. */
|
|
109
|
+
theme?: PartialCalendarTheme; /** Externally-owned per-hour row height (week/day). Created internally if omitted. */
|
|
110
|
+
cellHeight?: ReturnType<typeof useSharedValue<number>>; /** Initial per-hour row height in px (week/day). Default 64. */
|
|
111
|
+
hourHeight?: number;
|
|
112
|
+
minHourHeight?: number;
|
|
113
|
+
maxHourHeight?: number;
|
|
114
|
+
hourColumnWidth?: number; /** First hour shown on the week/day grid (0β23). Default 0. */
|
|
115
|
+
minHour?: number; /** Last hour shown on the week/day grid, exclusive (1β24). Default 24. */
|
|
116
|
+
maxHour?: number; /** Show hour labels in 12-hour AM/PM form. Default false (24h). */
|
|
117
|
+
ampm?: boolean; /** Initial vertical scroll, in minutes from midnight (week/day). */
|
|
118
|
+
scrollOffsetMinutes?: number; /** Show the current-time line on the week/day grid. Default true. */
|
|
119
|
+
showNowIndicator?: boolean; /** BCP-47 locale for weekday labels. Defaults to the device locale. */
|
|
120
|
+
locale?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Allow a fling to carry across several pages before snapping. Default false:
|
|
123
|
+
* one day/week/month per swipe.
|
|
124
|
+
*/
|
|
125
|
+
freeSwipe?: boolean; /** Custom header above the week/day grid. Receives the visible days. */
|
|
126
|
+
renderTimeGridHeader?: (days: Date[]) => React.ReactNode;
|
|
127
|
+
};
|
|
128
|
+
declare function Calendar<T>({
|
|
129
|
+
events,
|
|
130
|
+
mode,
|
|
131
|
+
date,
|
|
132
|
+
onChangeDate,
|
|
133
|
+
onPressEvent,
|
|
134
|
+
onPressDay,
|
|
135
|
+
onPressMore,
|
|
136
|
+
onPressCell,
|
|
137
|
+
maxVisibleEventCount,
|
|
138
|
+
weekStartsOn,
|
|
139
|
+
renderEvent,
|
|
140
|
+
keyExtractor,
|
|
141
|
+
theme,
|
|
142
|
+
cellHeight: cellHeightProp,
|
|
143
|
+
hourHeight,
|
|
144
|
+
minHourHeight,
|
|
145
|
+
maxHourHeight,
|
|
146
|
+
hourColumnWidth,
|
|
147
|
+
minHour,
|
|
148
|
+
maxHour,
|
|
149
|
+
ampm,
|
|
150
|
+
scrollOffsetMinutes,
|
|
151
|
+
showNowIndicator,
|
|
152
|
+
locale,
|
|
153
|
+
freeSwipe,
|
|
154
|
+
renderTimeGridHeader
|
|
155
|
+
}: CalendarProps<T>): import("react").JSX.Element;
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/components/MonthView.d.ts
|
|
158
|
+
type MonthViewProps<T> = {
|
|
159
|
+
date: Date;
|
|
160
|
+
events: CalendarEvent<T>[];
|
|
161
|
+
maxVisibleEventCount: number;
|
|
162
|
+
weekStartsOn: WeekStartsOn;
|
|
163
|
+
renderEvent: RenderEvent<T>;
|
|
164
|
+
keyExtractor: EventKeyExtractor<T>;
|
|
165
|
+
onPressDay?: (date: Date) => void;
|
|
166
|
+
onPressEvent: (event: CalendarEvent<T>) => void;
|
|
167
|
+
onPressMore?: (events: CalendarEvent<T>[], date: Date) => void;
|
|
168
|
+
};
|
|
169
|
+
declare function MonthViewInner<T>({
|
|
170
|
+
date,
|
|
171
|
+
events,
|
|
172
|
+
maxVisibleEventCount,
|
|
173
|
+
weekStartsOn,
|
|
174
|
+
renderEvent,
|
|
175
|
+
keyExtractor,
|
|
176
|
+
onPressDay,
|
|
177
|
+
onPressEvent,
|
|
178
|
+
onPressMore
|
|
179
|
+
}: MonthViewProps<T>): import("react").JSX.Element;
|
|
180
|
+
declare const MonthView: typeof MonthViewInner;
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/components/MonthPager.d.ts
|
|
183
|
+
type MonthPagerProps<T> = {
|
|
184
|
+
date: Date;
|
|
185
|
+
events: CalendarEvent<T>[];
|
|
186
|
+
maxVisibleEventCount: number;
|
|
187
|
+
weekStartsOn: WeekStartsOn;
|
|
188
|
+
renderEvent: RenderEvent<T>;
|
|
189
|
+
keyExtractor: EventKeyExtractor<T>;
|
|
190
|
+
onPressDay?: (date: Date) => void;
|
|
191
|
+
onPressEvent: (event: CalendarEvent<T>) => void;
|
|
192
|
+
onPressMore?: (events: CalendarEvent<T>[], date: Date) => void;
|
|
193
|
+
onChangeDate: (date: Date) => void;
|
|
194
|
+
freeSwipe?: boolean;
|
|
195
|
+
};
|
|
196
|
+
declare function MonthPagerInner<T>({
|
|
197
|
+
date,
|
|
198
|
+
events,
|
|
199
|
+
maxVisibleEventCount,
|
|
200
|
+
weekStartsOn,
|
|
201
|
+
renderEvent,
|
|
202
|
+
keyExtractor,
|
|
203
|
+
onPressDay,
|
|
204
|
+
onPressEvent,
|
|
205
|
+
onPressMore,
|
|
206
|
+
onChangeDate,
|
|
207
|
+
freeSwipe
|
|
208
|
+
}: MonthPagerProps<T>): import("react").JSX.Element;
|
|
209
|
+
declare const MonthPager: typeof MonthPagerInner;
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/components/TimeGrid.d.ts
|
|
212
|
+
declare const DEFAULT_HOUR_HEIGHT = 64;
|
|
213
|
+
type TimeGridProps<T> = {
|
|
214
|
+
mode: 'day' | 'week';
|
|
215
|
+
date: Date;
|
|
216
|
+
events: CalendarEvent<T>[];
|
|
217
|
+
cellHeight: SharedValue<number>; /** Initial per-hour row height in px; seeds scroll/zoom without reading the shared value during render. */
|
|
218
|
+
hourHeight?: number;
|
|
219
|
+
weekStartsOn: WeekStartsOn;
|
|
220
|
+
renderEvent: RenderEvent<T>;
|
|
221
|
+
keyExtractor: EventKeyExtractor<T>;
|
|
222
|
+
scrollOffsetMinutes?: number;
|
|
223
|
+
hourColumnWidth?: number; /** First hour shown (0β23). Default 0. */
|
|
224
|
+
minHour?: number; /** Last hour shown, exclusive (1β24). Default 24. */
|
|
225
|
+
maxHour?: number; /** Show hour labels in 12-hour AM/PM form. Default false (24h). */
|
|
226
|
+
ampm?: boolean;
|
|
227
|
+
minHourHeight?: number;
|
|
228
|
+
maxHourHeight?: number;
|
|
229
|
+
showNowIndicator?: boolean;
|
|
230
|
+
locale?: string;
|
|
231
|
+
freeSwipe?: boolean;
|
|
232
|
+
onPressEvent: (event: CalendarEvent<T>) => void;
|
|
233
|
+
onPressCell?: (date: Date) => void;
|
|
234
|
+
onChangeDate: (date: Date) => void; /** Optional header above the grid (e.g. weekday labels). Rendered full-width. */
|
|
235
|
+
renderHeader?: (days: Date[]) => React.ReactNode;
|
|
236
|
+
};
|
|
237
|
+
declare function TimeGridInner<T>({
|
|
238
|
+
mode,
|
|
239
|
+
date,
|
|
240
|
+
events,
|
|
241
|
+
cellHeight,
|
|
242
|
+
hourHeight,
|
|
243
|
+
weekStartsOn,
|
|
244
|
+
renderEvent,
|
|
245
|
+
keyExtractor,
|
|
246
|
+
scrollOffsetMinutes,
|
|
247
|
+
hourColumnWidth,
|
|
248
|
+
minHour,
|
|
249
|
+
maxHour,
|
|
250
|
+
ampm,
|
|
251
|
+
minHourHeight,
|
|
252
|
+
maxHourHeight,
|
|
253
|
+
showNowIndicator,
|
|
254
|
+
locale,
|
|
255
|
+
freeSwipe,
|
|
256
|
+
onPressEvent,
|
|
257
|
+
onPressCell,
|
|
258
|
+
onChangeDate,
|
|
259
|
+
renderHeader
|
|
260
|
+
}: TimeGridProps<T>): import("react").JSX.Element;
|
|
261
|
+
declare const TimeGrid: typeof TimeGridInner;
|
|
262
|
+
//#endregion
|
|
263
|
+
//#region src/components/DefaultEvent.d.ts
|
|
264
|
+
/**
|
|
265
|
+
* The built-in event renderer: a filled, rounded box showing the event title
|
|
266
|
+
* and (on the day/week grid) its time range. Pass your own `renderEvent` to
|
|
267
|
+
* `<Calendar>` to replace it entirely.
|
|
268
|
+
*/
|
|
269
|
+
declare function DefaultEvent<T>({
|
|
270
|
+
event,
|
|
271
|
+
mode,
|
|
272
|
+
onPress
|
|
273
|
+
}: RenderEventArgs<T>): import("react").JSX.Element;
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/utils/dates.d.ts
|
|
276
|
+
/** The seven dates of the week containing `date`, starting on `weekStartsOn`. */
|
|
277
|
+
declare const getWeekDays: (date: Date, weekStartsOn: WeekStartsOn) => Date[];
|
|
278
|
+
declare const isWeekend: (date: Date) => boolean;
|
|
279
|
+
declare const getIsToday: (date: Date) => boolean;
|
|
280
|
+
declare const isSameCalendarDay: (a: Date, b: Date) => boolean;
|
|
281
|
+
/** Minutes elapsed since midnight (0β1439). */
|
|
282
|
+
declare const minutesIntoDay: (date: Date) => number;
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/utils/layout.d.ts
|
|
285
|
+
type PositionedEvent<T> = {
|
|
286
|
+
event: CalendarEvent<T>; /** Hours from midnight to the event's segment start on this day (fractional). */
|
|
287
|
+
startHours: number; /** Segment duration in hours on this day (clamped to a small minimum). */
|
|
288
|
+
durationHours: number; /** Zero-based column index within its overlap cluster. */
|
|
289
|
+
column: number; /** Total columns in this event's overlap cluster. */
|
|
290
|
+
columns: number; /** True when the segment is clipped because the event continues before/after this day. */
|
|
291
|
+
continuesBefore: boolean;
|
|
292
|
+
continuesAfter: boolean;
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* Lay out a single day's events: events that overlap in time are split into
|
|
296
|
+
* side-by-side columns. Multi-day events are clipped to the portion that falls
|
|
297
|
+
* on `day` (e.g. a 23:00β01:00 event renders 23:00β24:00 on the start day and
|
|
298
|
+
* 00:00β01:00 on the next). Pure β safe to call per render, never per frame.
|
|
299
|
+
*/
|
|
300
|
+
declare function layoutDayEvents<T>(events: CalendarEvent<T>[], day: Date): PositionedEvent<T>[];
|
|
301
|
+
//#endregion
|
|
302
|
+
export { Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, DefaultEvent, type EventKeyExtractor, type ICalendarEvent, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type PartialCalendarTheme, type PositionedEvent, type RenderEvent, type RenderEventArgs, TimeGrid, type TimeGridProps, type WeekStartsOn, defaultTheme, getIsToday, getWeekDays, isSameCalendarDay, isWeekend, layoutDayEvents, mergeTheme, minutesIntoDay, useCalendarTheme };
|