@super-calendar/native 2.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/dist/DefaultMonthEvent-86XCNCge.d.ts +326 -0
- package/dist/DefaultMonthEvent-CpRoOloh.d.mts +326 -0
- package/dist/MonthList-BCfN-UGz.js +1089 -0
- package/dist/MonthList-CyrEJ_U6.mjs +1030 -0
- package/dist/index.d.mts +386 -0
- package/dist/index.d.ts +386 -0
- package/dist/index.js +1700 -0
- package/dist/index.mjs +1543 -0
- package/dist/picker.d.mts +3 -0
- package/dist/picker.d.ts +3 -0
- package/dist/picker.js +96 -0
- package/dist/picker.mjs +3 -0
- package/package.json +92 -0
- package/src/components/Agenda.tsx +133 -0
- package/src/components/AllDayLane.tsx +98 -0
- package/src/components/Calendar.tsx +456 -0
- package/src/components/DefaultEvent.tsx +223 -0
- package/src/components/DefaultMonthEvent.tsx +105 -0
- package/src/components/MonthList.tsx +570 -0
- package/src/components/MonthPager.tsx +377 -0
- package/src/components/MonthView.tsx +518 -0
- package/src/components/TimeGrid.tsx +1943 -0
- package/src/index.tsx +70 -0
- package/src/picker.tsx +55 -0
- package/src/theme.ts +86 -0
- package/src/types.ts +62 -0
- package/src/utils/useWebGridZoom.ts +59 -0
- package/src/utils/useWebPagerKeys.ts +56 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { C as defaultTheme, S as darkTheme, T as useCalendarTheme, a as MonthPagerProps, b as CalendarThemeProvider, d as EventKeyExtractor, f as ICalendarEvent, g as RenderEventArgs, h as RenderEvent, i as MonthPager, l as CalendarEvent, n as MonthList, o as MonthView, r as MonthListProps, s as MonthViewProps, t as DefaultMonthEvent, u as CalendarMode, v as WeekStartsOn, w as mergeTheme, x as PartialCalendarTheme, y as CalendarTheme } from "./DefaultMonthEvent-CpRoOloh.mjs";
|
|
2
|
+
import { DateRange, DateSelectionConstraints, DaySelectionState, MonthGrid, MonthGridDay, MonthGridWeek, MonthGridWeekday, UseDateRangeOptions, UseMonthGridOptions, buildMonthGrid, buildMonthWeeks, daySelectionState, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, minutesIntoDay, nextDateRange, useDateRange, useMonthGrid } from "@super-calendar/core";
|
|
3
|
+
export { type CalendarEvent, type CalendarMode, type CalendarTheme, CalendarThemeProvider, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultMonthEvent, type EventKeyExtractor, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type PartialCalendarTheme, type RenderEvent, type RenderEventArgs, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, mergeTheme, minutesIntoDay, nextDateRange, useCalendarTheme, useDateRange, useMonthGrid };
|
package/dist/picker.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { C as defaultTheme, S as darkTheme, T as useCalendarTheme, a as MonthPagerProps, b as CalendarThemeProvider, d as EventKeyExtractor, f as ICalendarEvent, g as RenderEventArgs, h as RenderEvent, i as MonthPager, l as CalendarEvent, n as MonthList, o as MonthView, r as MonthListProps, s as MonthViewProps, t as DefaultMonthEvent, u as CalendarMode, v as WeekStartsOn, w as mergeTheme, x as PartialCalendarTheme, y as CalendarTheme } from "./DefaultMonthEvent-86XCNCge.js";
|
|
2
|
+
import { DateRange, DateSelectionConstraints, DaySelectionState, MonthGrid, MonthGridDay, MonthGridWeek, MonthGridWeekday, UseDateRangeOptions, UseMonthGridOptions, buildMonthGrid, buildMonthWeeks, daySelectionState, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, minutesIntoDay, nextDateRange, useDateRange, useMonthGrid } from "@super-calendar/core";
|
|
3
|
+
export { type CalendarEvent, type CalendarMode, type CalendarTheme, CalendarThemeProvider, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultMonthEvent, type EventKeyExtractor, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type PartialCalendarTheme, type RenderEvent, type RenderEventArgs, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, mergeTheme, minutesIntoDay, nextDateRange, useCalendarTheme, useDateRange, useMonthGrid };
|
package/dist/picker.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_MonthList = require("./MonthList-BCfN-UGz.js");
|
|
3
|
+
let _super_calendar_core = require("@super-calendar/core");
|
|
4
|
+
exports.CalendarThemeProvider = require_MonthList.CalendarThemeProvider;
|
|
5
|
+
exports.DefaultMonthEvent = require_MonthList.DefaultMonthEvent;
|
|
6
|
+
exports.MonthList = require_MonthList.MonthList;
|
|
7
|
+
exports.MonthPager = require_MonthList.MonthPager;
|
|
8
|
+
exports.MonthView = require_MonthList.MonthView;
|
|
9
|
+
Object.defineProperty(exports, "buildMonthGrid", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function() {
|
|
12
|
+
return _super_calendar_core.buildMonthGrid;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, "buildMonthWeeks", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function() {
|
|
18
|
+
return _super_calendar_core.buildMonthWeeks;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
exports.darkTheme = require_MonthList.darkTheme;
|
|
22
|
+
Object.defineProperty(exports, "daySelectionState", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function() {
|
|
25
|
+
return _super_calendar_core.daySelectionState;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
exports.defaultTheme = require_MonthList.defaultTheme;
|
|
29
|
+
Object.defineProperty(exports, "getIsToday", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get: function() {
|
|
32
|
+
return _super_calendar_core.getIsToday;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
Object.defineProperty(exports, "getWeekDays", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
get: function() {
|
|
38
|
+
return _super_calendar_core.getWeekDays;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
Object.defineProperty(exports, "isDateSelectable", {
|
|
42
|
+
enumerable: true,
|
|
43
|
+
get: function() {
|
|
44
|
+
return _super_calendar_core.isDateSelectable;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
Object.defineProperty(exports, "isRangeEndpoint", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
get: function() {
|
|
50
|
+
return _super_calendar_core.isRangeEndpoint;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
Object.defineProperty(exports, "isSameCalendarDay", {
|
|
54
|
+
enumerable: true,
|
|
55
|
+
get: function() {
|
|
56
|
+
return _super_calendar_core.isSameCalendarDay;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
Object.defineProperty(exports, "isWeekend", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
get: function() {
|
|
62
|
+
return _super_calendar_core.isWeekend;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
Object.defineProperty(exports, "isWithinDateRange", {
|
|
66
|
+
enumerable: true,
|
|
67
|
+
get: function() {
|
|
68
|
+
return _super_calendar_core.isWithinDateRange;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
exports.mergeTheme = require_MonthList.mergeTheme;
|
|
72
|
+
Object.defineProperty(exports, "minutesIntoDay", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function() {
|
|
75
|
+
return _super_calendar_core.minutesIntoDay;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "nextDateRange", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function() {
|
|
81
|
+
return _super_calendar_core.nextDateRange;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
exports.useCalendarTheme = require_MonthList.useCalendarTheme;
|
|
85
|
+
Object.defineProperty(exports, "useDateRange", {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get: function() {
|
|
88
|
+
return _super_calendar_core.useDateRange;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
Object.defineProperty(exports, "useMonthGrid", {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
get: function() {
|
|
94
|
+
return _super_calendar_core.useMonthGrid;
|
|
95
|
+
}
|
|
96
|
+
});
|
package/dist/picker.mjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { c as defaultTheme, i as MonthView, l as mergeTheme, n as DefaultMonthEvent, o as CalendarThemeProvider, r as MonthPager, s as darkTheme, t as MonthList, u as useCalendarTheme } from "./MonthList-CyrEJ_U6.mjs";
|
|
2
|
+
import { buildMonthGrid, buildMonthWeeks, daySelectionState, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, minutesIntoDay, nextDateRange, useDateRange, useMonthGrid } from "@super-calendar/core";
|
|
3
|
+
export { CalendarThemeProvider, DefaultMonthEvent, MonthList, MonthPager, MonthView, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, mergeTheme, minutesIntoDay, nextDateRange, useCalendarTheme, useDateRange, useMonthGrid };
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@super-calendar/native",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Gesture-driven, virtualized month / week / day calendar and date picker for React Native (and web via react-native-web).",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agenda",
|
|
7
|
+
"calendar",
|
|
8
|
+
"date-picker",
|
|
9
|
+
"expo",
|
|
10
|
+
"month-view",
|
|
11
|
+
"range-picker",
|
|
12
|
+
"react-native",
|
|
13
|
+
"reanimated",
|
|
14
|
+
"timetable",
|
|
15
|
+
"week-view"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/afonsojramos/react-native-super-calendar#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/afonsojramos/react-native-super-calendar/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/afonsojramos/react-native-super-calendar.git",
|
|
25
|
+
"directory": "packages/native"
|
|
26
|
+
},
|
|
27
|
+
"source": "./src/index.tsx",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"src",
|
|
31
|
+
"!**/__tests__"
|
|
32
|
+
],
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"main": "./dist/index.js",
|
|
35
|
+
"module": "./dist/index.mjs",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"react-native": "./src/index.tsx",
|
|
38
|
+
"exports": {
|
|
39
|
+
".": {
|
|
40
|
+
"react-native": "./src/index.tsx",
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/index.d.mts",
|
|
43
|
+
"default": "./dist/index.mjs"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/index.d.ts",
|
|
47
|
+
"default": "./dist/index.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"./picker": {
|
|
51
|
+
"react-native": "./src/picker.tsx",
|
|
52
|
+
"import": {
|
|
53
|
+
"types": "./dist/picker.d.mts",
|
|
54
|
+
"default": "./dist/picker.mjs"
|
|
55
|
+
},
|
|
56
|
+
"require": {
|
|
57
|
+
"types": "./dist/picker.d.ts",
|
|
58
|
+
"default": "./dist/picker.js"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"./package.json": "./package.json"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@super-calendar/core": "2.0.0"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"@legendapp/list": ">=3",
|
|
71
|
+
"date-fns": ">=3",
|
|
72
|
+
"react": ">=18",
|
|
73
|
+
"react-native": ">=0.74",
|
|
74
|
+
"react-native-gesture-handler": ">=2.16",
|
|
75
|
+
"react-native-reanimated": ">=4.0.0 <5",
|
|
76
|
+
"react-native-worklets": ">=0.5"
|
|
77
|
+
},
|
|
78
|
+
"peerDependenciesMeta": {
|
|
79
|
+
"react-native-gesture-handler": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"react-native-reanimated": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"react-native-worklets": {
|
|
86
|
+
"optional": true
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsdown"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { LegendList, type LegendListRenderItemProps } from "@legendapp/list/react-native";
|
|
2
|
+
import { format, isSameDay, type Locale, startOfDay } from "date-fns";
|
|
3
|
+
import { type ComponentType, useCallback, useMemo } from "react";
|
|
4
|
+
import { StyleSheet, Text, View } from "react-native";
|
|
5
|
+
import { useCalendarTheme } from "../theme";
|
|
6
|
+
import type { CalendarEvent, EventKeyExtractor, RenderEvent } from "../types";
|
|
7
|
+
import { getIsToday } from "@super-calendar/core";
|
|
8
|
+
import { isAllDayEvent } from "@super-calendar/core";
|
|
9
|
+
|
|
10
|
+
export type AgendaProps<T> = {
|
|
11
|
+
events: CalendarEvent<T>[];
|
|
12
|
+
locale?: Locale;
|
|
13
|
+
renderEvent: RenderEvent<T>;
|
|
14
|
+
keyExtractor: EventKeyExtractor<T>;
|
|
15
|
+
onPressEvent: (event: CalendarEvent<T>) => void;
|
|
16
|
+
onLongPressEvent?: (event: CalendarEvent<T>) => void;
|
|
17
|
+
onPressDay?: (date: Date) => void;
|
|
18
|
+
/** Highlight this date's header instead of the real "today". */
|
|
19
|
+
activeDate?: Date;
|
|
20
|
+
/** Drawn between rows of the agenda list. */
|
|
21
|
+
itemSeparatorComponent?: ComponentType<unknown> | null;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type Row<T> =
|
|
25
|
+
| { kind: "header"; date: Date; key: string }
|
|
26
|
+
| { kind: "event"; event: CalendarEvent<T>; index: number; key: string };
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A vertical, day-grouped list of events (no time grid). Events are sorted by
|
|
30
|
+
* start, grouped under a date header per day. The consumer controls which
|
|
31
|
+
* events (and therefore which date range) are shown.
|
|
32
|
+
*/
|
|
33
|
+
export function Agenda<T>({
|
|
34
|
+
events,
|
|
35
|
+
locale,
|
|
36
|
+
renderEvent,
|
|
37
|
+
keyExtractor,
|
|
38
|
+
onPressEvent,
|
|
39
|
+
onLongPressEvent,
|
|
40
|
+
onPressDay,
|
|
41
|
+
activeDate,
|
|
42
|
+
itemSeparatorComponent,
|
|
43
|
+
}: AgendaProps<T>) {
|
|
44
|
+
const theme = useCalendarTheme();
|
|
45
|
+
const RenderEventComponent = renderEvent;
|
|
46
|
+
|
|
47
|
+
const rows = useMemo<Row<T>[]>(() => {
|
|
48
|
+
const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
49
|
+
const out: Row<T>[] = [];
|
|
50
|
+
let currentDay: Date | null = null;
|
|
51
|
+
sorted.forEach((event, index) => {
|
|
52
|
+
if (!currentDay || !isSameDay(event.start, currentDay)) {
|
|
53
|
+
currentDay = startOfDay(event.start);
|
|
54
|
+
out.push({ kind: "header", date: currentDay, key: `h-${currentDay.toISOString()}` });
|
|
55
|
+
}
|
|
56
|
+
out.push({ kind: "event", event, index, key: `e-${keyExtractor(event, index)}` });
|
|
57
|
+
});
|
|
58
|
+
return out;
|
|
59
|
+
}, [events, keyExtractor]);
|
|
60
|
+
|
|
61
|
+
const keyExtractorRow = useCallback((row: Row<T>) => row.key, []);
|
|
62
|
+
const renderItem = useCallback(
|
|
63
|
+
({ item }: LegendListRenderItemProps<Row<T>>) => {
|
|
64
|
+
if (item.kind === "header") {
|
|
65
|
+
const isHighlighted = activeDate ? isSameDay(item.date, activeDate) : getIsToday(item.date);
|
|
66
|
+
return (
|
|
67
|
+
<Text
|
|
68
|
+
style={[
|
|
69
|
+
styles.header,
|
|
70
|
+
{ color: isHighlighted ? theme.colors.todayBackground : theme.colors.textMuted },
|
|
71
|
+
]}
|
|
72
|
+
onPress={onPressDay ? () => onPressDay(item.date) : undefined}
|
|
73
|
+
accessibilityRole={onPressDay ? "button" : "header"}
|
|
74
|
+
>
|
|
75
|
+
{format(item.date, "EEEE, d LLLL", { locale })}
|
|
76
|
+
</Text>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return (
|
|
80
|
+
<View style={styles.eventRow}>
|
|
81
|
+
<RenderEventComponent
|
|
82
|
+
event={item.event}
|
|
83
|
+
mode="schedule"
|
|
84
|
+
isAllDay={isAllDayEvent(item.event)}
|
|
85
|
+
onPress={() => onPressEvent(item.event)}
|
|
86
|
+
onLongPress={onLongPressEvent ? () => onLongPressEvent(item.event) : undefined}
|
|
87
|
+
/>
|
|
88
|
+
</View>
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
[theme, locale, activeDate, onPressDay, onPressEvent, onLongPressEvent, RenderEventComponent],
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (rows.length === 0) {
|
|
95
|
+
return <Text style={[styles.empty, { color: theme.colors.textMuted }]}>No events</Text>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<LegendList
|
|
100
|
+
style={styles.list}
|
|
101
|
+
data={rows}
|
|
102
|
+
keyExtractor={keyExtractorRow}
|
|
103
|
+
renderItem={renderItem}
|
|
104
|
+
// The public prop is data-agnostic; LegendList types the separator by row.
|
|
105
|
+
ItemSeparatorComponent={
|
|
106
|
+
(itemSeparatorComponent ?? undefined) as ComponentType<{ leadingItem: Row<T> }> | undefined
|
|
107
|
+
}
|
|
108
|
+
recycleItems={false}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const styles = StyleSheet.create({
|
|
114
|
+
list: {
|
|
115
|
+
flex: 1,
|
|
116
|
+
},
|
|
117
|
+
header: {
|
|
118
|
+
fontSize: 13,
|
|
119
|
+
fontWeight: "600",
|
|
120
|
+
paddingTop: 12,
|
|
121
|
+
paddingBottom: 4,
|
|
122
|
+
paddingHorizontal: 12,
|
|
123
|
+
},
|
|
124
|
+
eventRow: {
|
|
125
|
+
paddingHorizontal: 12,
|
|
126
|
+
paddingVertical: 2,
|
|
127
|
+
},
|
|
128
|
+
empty: {
|
|
129
|
+
fontSize: 14,
|
|
130
|
+
paddingVertical: 16,
|
|
131
|
+
paddingHorizontal: 12,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { addDays, startOfDay } from "date-fns";
|
|
2
|
+
import { StyleSheet, Text, View } from "react-native";
|
|
3
|
+
import { useCalendarTheme } from "../theme";
|
|
4
|
+
import type { CalendarEvent, CalendarMode, EventKeyExtractor, RenderEvent } from "../types";
|
|
5
|
+
import { isAllDayEvent } from "@super-calendar/core";
|
|
6
|
+
|
|
7
|
+
type AllDayLaneProps<T> = {
|
|
8
|
+
days: Date[];
|
|
9
|
+
events: CalendarEvent<T>[];
|
|
10
|
+
mode: CalendarMode;
|
|
11
|
+
hourColumnWidth: number;
|
|
12
|
+
dayWidth: number;
|
|
13
|
+
renderEvent: RenderEvent<T>;
|
|
14
|
+
keyExtractor: EventKeyExtractor<T>;
|
|
15
|
+
onPressEvent: (event: CalendarEvent<T>) => void;
|
|
16
|
+
onLongPressEvent?: (event: CalendarEvent<T>) => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The all-day lane that sits above the scrolling time grid. All-day events are
|
|
21
|
+
* excluded from the timed columns (see `layoutDayEvents`) and shown here,
|
|
22
|
+
* stacked under their day(s). Renders nothing when no day has an all-day event,
|
|
23
|
+
* so timed-only calendars are unaffected.
|
|
24
|
+
*/
|
|
25
|
+
export function AllDayLane<T>({
|
|
26
|
+
days,
|
|
27
|
+
events,
|
|
28
|
+
mode,
|
|
29
|
+
hourColumnWidth,
|
|
30
|
+
dayWidth,
|
|
31
|
+
renderEvent,
|
|
32
|
+
keyExtractor,
|
|
33
|
+
onPressEvent,
|
|
34
|
+
onLongPressEvent,
|
|
35
|
+
}: AllDayLaneProps<T>) {
|
|
36
|
+
const theme = useCalendarTheme();
|
|
37
|
+
const RenderEventComponent = renderEvent;
|
|
38
|
+
|
|
39
|
+
const allDay = events.filter(isAllDayEvent);
|
|
40
|
+
const perDay = days.map((day) => {
|
|
41
|
+
const start = startOfDay(day);
|
|
42
|
+
const next = addDays(start, 1);
|
|
43
|
+
return allDay.filter((event) => event.start < next && event.end > start);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (perDay.every((list) => list.length === 0)) return null;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<View style={[styles.lane, { borderBottomColor: theme.colors.gridLine }]}>
|
|
50
|
+
<View style={[styles.gutter, { width: hourColumnWidth }]}>
|
|
51
|
+
{/* The "all-day" gutter label, mirroring the dom renderer: small, muted,
|
|
52
|
+
and right-aligned against the timed columns. Centered vertically so it
|
|
53
|
+
lines up with the chips whether the lane holds one event or several. */}
|
|
54
|
+
<Text style={[styles.label, { color: theme.colors.textMuted }]} allowFontScaling={false}>
|
|
55
|
+
all-day
|
|
56
|
+
</Text>
|
|
57
|
+
</View>
|
|
58
|
+
{days.map((day, dayIndex) => (
|
|
59
|
+
<View key={day.toISOString()} style={[styles.column, { width: dayWidth }]}>
|
|
60
|
+
{perDay[dayIndex].map((event, index) => (
|
|
61
|
+
<View key={keyExtractor(event, index)} style={styles.chip}>
|
|
62
|
+
<RenderEventComponent
|
|
63
|
+
event={event}
|
|
64
|
+
mode={mode}
|
|
65
|
+
isAllDay
|
|
66
|
+
onPress={() => onPressEvent(event)}
|
|
67
|
+
onLongPress={onLongPressEvent ? () => onLongPressEvent(event) : undefined}
|
|
68
|
+
/>
|
|
69
|
+
</View>
|
|
70
|
+
))}
|
|
71
|
+
</View>
|
|
72
|
+
))}
|
|
73
|
+
</View>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const styles = StyleSheet.create({
|
|
78
|
+
lane: {
|
|
79
|
+
flexDirection: "row",
|
|
80
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
81
|
+
},
|
|
82
|
+
gutter: {
|
|
83
|
+
justifyContent: "center",
|
|
84
|
+
},
|
|
85
|
+
label: {
|
|
86
|
+
fontSize: 10,
|
|
87
|
+
textAlign: "right",
|
|
88
|
+
paddingRight: 6,
|
|
89
|
+
},
|
|
90
|
+
column: {
|
|
91
|
+
paddingVertical: 2,
|
|
92
|
+
paddingHorizontal: 1,
|
|
93
|
+
gap: 2,
|
|
94
|
+
},
|
|
95
|
+
chip: {
|
|
96
|
+
minHeight: 18,
|
|
97
|
+
},
|
|
98
|
+
});
|