@dreamstack-us/kaal 0.0.1 → 0.0.3
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 +165 -0
- package/lib/module/components/CalendarGrid/CalendarGrid.js +125 -29
- package/lib/module/components/CalendarGrid/CalendarGrid.js.map +1 -1
- package/lib/module/components/CalendarGrid/CalendarGrid.styles.js +22 -17
- package/lib/module/components/CalendarGrid/CalendarGrid.styles.js.map +1 -1
- package/lib/module/components/CalendarGrid/CalendarGrid.web.js +265 -0
- package/lib/module/components/CalendarGrid/CalendarGrid.web.js.map +1 -0
- package/lib/module/components/CalendarGrid/DayCell.js +77 -53
- package/lib/module/components/CalendarGrid/DayCell.js.map +1 -1
- package/lib/module/components/CalendarGrid/DayCell.web.js +124 -0
- package/lib/module/components/CalendarGrid/DayCell.web.js.map +1 -0
- package/lib/module/components/CalendarGrid/index.js +1 -1
- package/lib/module/components/CalendarGrid/index.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.android.js +53 -21
- package/lib/module/components/DatePicker/DatePicker.android.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.ios.js +55 -23
- package/lib/module/components/DatePicker/DatePicker.ios.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.styles.js +19 -20
- package/lib/module/components/DatePicker/DatePicker.styles.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.web.js +59 -21
- package/lib/module/components/DatePicker/DatePicker.web.js.map +1 -1
- package/lib/module/components/TimePicker/ClockFace.js +27 -7
- package/lib/module/components/TimePicker/ClockFace.js.map +1 -1
- package/lib/module/components/TimePicker/ClockFace.web.js +253 -0
- package/lib/module/components/TimePicker/ClockFace.web.js.map +1 -0
- package/lib/module/components/TimePicker/MaterialTimePicker.js +68 -16
- package/lib/module/components/TimePicker/MaterialTimePicker.js.map +1 -1
- package/lib/module/components/TimePicker/MaterialTimePicker.web.js +231 -0
- package/lib/module/components/TimePicker/MaterialTimePicker.web.js.map +1 -0
- package/lib/module/components/TimePicker/TimePicker.android.js +13 -6
- package/lib/module/components/TimePicker/TimePicker.android.js.map +1 -1
- package/lib/module/components/TimePicker/TimePicker.ios.js +14 -7
- package/lib/module/components/TimePicker/TimePicker.ios.js.map +1 -1
- package/lib/module/components/TimePicker/TimePicker.styles.js +53 -45
- package/lib/module/components/TimePicker/TimePicker.styles.js.map +1 -1
- package/lib/module/components/TimePicker/TimePicker.web.js +24 -12
- package/lib/module/components/TimePicker/TimePicker.web.js.map +1 -1
- package/lib/module/components/TimePicker/TimeWheelPicker.js +45 -10
- package/lib/module/components/TimePicker/TimeWheelPicker.js.map +1 -1
- package/lib/module/components/TimePicker/TimeWheelPicker.web.js +339 -0
- package/lib/module/components/TimePicker/TimeWheelPicker.web.js.map +1 -0
- package/lib/module/components/TimePicker/index.js +3 -3
- package/lib/module/components/TimePicker/index.js.map +1 -1
- package/lib/module/components/WheelPicker/WheelPicker.js +21 -2
- package/lib/module/components/WheelPicker/WheelPicker.js.map +1 -1
- package/lib/module/components/WheelPicker/WheelPicker.styles.js +13 -8
- package/lib/module/components/WheelPicker/WheelPicker.styles.js.map +1 -1
- package/lib/module/components/WheelPicker/WheelPicker.web.js +146 -57
- package/lib/module/components/WheelPicker/WheelPicker.web.js.map +1 -1
- package/lib/module/context/ThemeOverrideContext.js +34 -0
- package/lib/module/context/ThemeOverrideContext.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/validation.js +74 -34
- package/lib/module/utils/validation.js.map +1 -1
- package/lib/typescript/components/CalendarGrid/CalendarGrid.d.ts +24 -3
- package/lib/typescript/components/CalendarGrid/CalendarGrid.d.ts.map +1 -1
- package/lib/typescript/components/CalendarGrid/CalendarGrid.styles.d.ts +12 -10
- package/lib/typescript/components/CalendarGrid/CalendarGrid.styles.d.ts.map +1 -1
- package/lib/typescript/components/CalendarGrid/CalendarGrid.web.d.ts +33 -0
- package/lib/typescript/components/CalendarGrid/CalendarGrid.web.d.ts.map +1 -0
- package/lib/typescript/components/CalendarGrid/DayCell.d.ts +3 -0
- package/lib/typescript/components/CalendarGrid/DayCell.d.ts.map +1 -1
- package/lib/typescript/components/CalendarGrid/DayCell.web.d.ts +15 -0
- package/lib/typescript/components/CalendarGrid/DayCell.web.d.ts.map +1 -0
- package/lib/typescript/components/DatePicker/DatePicker.android.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.d.ts +27 -4
- package/lib/typescript/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.ios.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.styles.d.ts +12 -13
- package/lib/typescript/components/DatePicker/DatePicker.styles.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.web.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/ClockFace.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/ClockFace.web.d.ts +12 -0
- package/lib/typescript/components/TimePicker/ClockFace.web.d.ts.map +1 -0
- package/lib/typescript/components/TimePicker/MaterialTimePicker.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/MaterialTimePicker.web.d.ts +12 -0
- package/lib/typescript/components/TimePicker/MaterialTimePicker.web.d.ts.map +1 -0
- package/lib/typescript/components/TimePicker/TimePicker.android.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/TimePicker.ios.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/TimePicker.styles.d.ts +29 -25
- package/lib/typescript/components/TimePicker/TimePicker.styles.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/TimePicker.web.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/TimeWheelPicker.d.ts.map +1 -1
- package/lib/typescript/components/TimePicker/TimeWheelPicker.web.d.ts +11 -0
- package/lib/typescript/components/TimePicker/TimeWheelPicker.web.d.ts.map +1 -0
- package/lib/typescript/components/WheelPicker/WheelPicker.d.ts +14 -1
- package/lib/typescript/components/WheelPicker/WheelPicker.d.ts.map +1 -1
- package/lib/typescript/components/WheelPicker/WheelPicker.styles.d.ts +9 -7
- package/lib/typescript/components/WheelPicker/WheelPicker.styles.d.ts.map +1 -1
- package/lib/typescript/components/WheelPicker/WheelPicker.web.d.ts.map +1 -1
- package/lib/typescript/context/ThemeOverrideContext.d.ts +23 -0
- package/lib/typescript/context/ThemeOverrideContext.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +4 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/types/datepicker.d.ts +78 -3
- package/lib/typescript/types/datepicker.d.ts.map +1 -1
- package/lib/typescript/types/timepicker.d.ts +62 -0
- package/lib/typescript/types/timepicker.d.ts.map +1 -1
- package/lib/typescript/utils/validation.d.ts +47 -27
- package/lib/typescript/utils/validation.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/components/CalendarGrid/CalendarGrid.styles.ts +21 -17
- package/src/components/CalendarGrid/CalendarGrid.tsx +265 -85
- package/src/components/CalendarGrid/CalendarGrid.web.tsx +396 -0
- package/src/components/CalendarGrid/DayCell.tsx +122 -61
- package/src/components/CalendarGrid/DayCell.web.tsx +171 -0
- package/src/components/DatePicker/DatePicker.android.tsx +48 -24
- package/src/components/DatePicker/DatePicker.ios.tsx +51 -27
- package/src/components/DatePicker/DatePicker.styles.ts +18 -22
- package/src/components/DatePicker/DatePicker.tsx +35 -4
- package/src/components/DatePicker/DatePicker.web.tsx +55 -23
- package/src/components/TimePicker/ClockFace.tsx +34 -8
- package/src/components/TimePicker/ClockFace.web.tsx +303 -0
- package/src/components/TimePicker/MaterialTimePicker.tsx +144 -13
- package/src/components/TimePicker/MaterialTimePicker.web.tsx +271 -0
- package/src/components/TimePicker/TimePicker.android.tsx +9 -1
- package/src/components/TimePicker/TimePicker.ios.tsx +10 -6
- package/src/components/TimePicker/TimePicker.styles.ts +52 -45
- package/src/components/TimePicker/TimePicker.web.tsx +17 -7
- package/src/components/TimePicker/TimeWheelPicker.tsx +60 -6
- package/src/components/TimePicker/TimeWheelPicker.web.tsx +401 -0
- package/src/components/WheelPicker/WheelPicker.styles.ts +12 -8
- package/src/components/WheelPicker/WheelPicker.tsx +24 -2
- package/src/components/WheelPicker/WheelPicker.web.tsx +153 -57
- package/src/context/ThemeOverrideContext.tsx +38 -0
- package/src/index.ts +13 -0
- package/src/types/datepicker.ts +87 -3
- package/src/types/timepicker.ts +74 -0
- package/src/utils/validation.ts +111 -55
- package/lib/module/unistyles.js +0 -9
- package/lib/module/unistyles.js.map +0 -1
- package/lib/typescript/unistyles.d.ts +0 -3
- package/lib/typescript/unistyles.d.ts.map +0 -1
- package/src/unistyles.ts +0 -6
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { memo, useCallback, useMemo } from 'react';
|
|
2
2
|
import { FlatList, Pressable, Text, View } from 'react-native';
|
|
3
|
+
import { useDatePickerOverrides } from '../../context/ThemeOverrideContext';
|
|
3
4
|
import {
|
|
4
5
|
addMonths,
|
|
5
6
|
compareDates,
|
|
@@ -13,23 +14,83 @@ import {
|
|
|
13
14
|
import { styles } from './CalendarGrid.styles';
|
|
14
15
|
import { DayCell } from './DayCell';
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import type { DateRange } from '../../types/datepicker';
|
|
18
|
+
|
|
19
|
+
interface CalendarGridBaseProps {
|
|
19
20
|
minDate?: Date;
|
|
20
21
|
maxDate?: Date;
|
|
21
22
|
disabledDates?: Date[];
|
|
22
23
|
themeMode: 'ios' | 'android' | 'custom';
|
|
24
|
+
/**
|
|
25
|
+
* First day of the week: 0 = Sunday, 1 = Monday
|
|
26
|
+
* @default 0 (Sunday)
|
|
27
|
+
*/
|
|
28
|
+
weekStartsOn?: 0 | 1;
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
interface CalendarGridSingleProps extends CalendarGridBaseProps {
|
|
32
|
+
selectionMode?: 'single';
|
|
33
|
+
value: Date;
|
|
34
|
+
onChange: (date: Date) => void;
|
|
35
|
+
startDate?: never;
|
|
36
|
+
endDate?: never;
|
|
37
|
+
onRangeChange?: never;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface CalendarGridRangeProps extends CalendarGridBaseProps {
|
|
41
|
+
selectionMode: 'range';
|
|
42
|
+
startDate: Date | null;
|
|
43
|
+
endDate: Date | null;
|
|
44
|
+
onRangeChange: (range: DateRange) => void;
|
|
45
|
+
value?: never;
|
|
46
|
+
onChange?: never;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type CalendarGridProps = CalendarGridSingleProps | CalendarGridRangeProps;
|
|
50
|
+
|
|
25
51
|
const CELL_SIZE = 44;
|
|
26
|
-
const WEEK_DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
|
27
52
|
|
|
28
|
-
|
|
53
|
+
// Week day labels starting from Sunday
|
|
54
|
+
const WEEK_DAYS_SUNDAY_START = [
|
|
55
|
+
'Sun',
|
|
56
|
+
'Mon',
|
|
57
|
+
'Tue',
|
|
58
|
+
'Wed',
|
|
59
|
+
'Thu',
|
|
60
|
+
'Fri',
|
|
61
|
+
'Sat',
|
|
62
|
+
];
|
|
63
|
+
const WEEK_DAYS_MONDAY_START = [
|
|
64
|
+
'Mon',
|
|
65
|
+
'Tue',
|
|
66
|
+
'Wed',
|
|
67
|
+
'Thu',
|
|
68
|
+
'Fri',
|
|
69
|
+
'Sat',
|
|
70
|
+
'Sun',
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Generate padding days for the month grid based on week start day
|
|
75
|
+
* TODO: This logic should be refactored when adding locale support
|
|
76
|
+
*/
|
|
77
|
+
const generateMonthDays = (
|
|
78
|
+
currentMonth: Date,
|
|
79
|
+
weekStartsOn: 0 | 1,
|
|
80
|
+
): (Date | null)[] => {
|
|
29
81
|
const firstDay = getFirstDayOfMonth(currentMonth);
|
|
30
|
-
// getDayOfWeek returns 0 for Sunday,
|
|
31
|
-
const
|
|
32
|
-
|
|
82
|
+
// getDayOfWeek returns 0 for Sunday, 1 for Monday, etc.
|
|
83
|
+
const dayOfWeek = getDayOfWeek(firstDay);
|
|
84
|
+
|
|
85
|
+
// Calculate padding days based on week start
|
|
86
|
+
let paddingDays: number;
|
|
87
|
+
if (weekStartsOn === 0) {
|
|
88
|
+
// Sunday start: Sunday = 0 padding, Monday = 1, etc.
|
|
89
|
+
paddingDays = dayOfWeek;
|
|
90
|
+
} else {
|
|
91
|
+
// Monday start: Monday = 0 padding, Sunday = 6 padding
|
|
92
|
+
paddingDays = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
|
93
|
+
}
|
|
33
94
|
|
|
34
95
|
const days: (Date | null)[] = [];
|
|
35
96
|
|
|
@@ -55,97 +116,216 @@ const generateMonthDays = (currentMonth: Date): (Date | null)[] => {
|
|
|
55
116
|
return days;
|
|
56
117
|
};
|
|
57
118
|
|
|
58
|
-
export const CalendarGrid: React.FC<CalendarGridProps> = memo(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
119
|
+
export const CalendarGrid: React.FC<CalendarGridProps> = memo((props) => {
|
|
120
|
+
const {
|
|
121
|
+
minDate,
|
|
122
|
+
maxDate,
|
|
123
|
+
disabledDates,
|
|
124
|
+
themeMode,
|
|
125
|
+
weekStartsOn = 0,
|
|
126
|
+
selectionMode = 'single',
|
|
127
|
+
} = props;
|
|
128
|
+
|
|
129
|
+
// Extract mode-specific props
|
|
130
|
+
const singleValue = selectionMode === 'single' ? props.value : null;
|
|
131
|
+
const singleOnChange = selectionMode === 'single' ? props.onChange : null;
|
|
132
|
+
const rangeStart = selectionMode === 'range' ? props.startDate : null;
|
|
133
|
+
const rangeEnd = selectionMode === 'range' ? props.endDate : null;
|
|
134
|
+
const rangeOnChange = selectionMode === 'range' ? props.onRangeChange : null;
|
|
63
135
|
|
|
64
|
-
|
|
136
|
+
const overrides = useDatePickerOverrides();
|
|
137
|
+
const [currentMonth, setCurrentMonth] = React.useState(() =>
|
|
138
|
+
getFirstDayOfMonth(singleValue ?? rangeStart ?? new Date()),
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const days = useMemo(
|
|
142
|
+
() => generateMonthDays(currentMonth, weekStartsOn),
|
|
143
|
+
[currentMonth, weekStartsOn],
|
|
144
|
+
);
|
|
65
145
|
|
|
66
|
-
|
|
146
|
+
const weekDays =
|
|
147
|
+
weekStartsOn === 0 ? WEEK_DAYS_SUNDAY_START : WEEK_DAYS_MONDAY_START;
|
|
67
148
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
149
|
+
const todayDate = useMemo(() => today(), []);
|
|
150
|
+
|
|
151
|
+
const isDisabled = useCallback(
|
|
152
|
+
(date: Date | null): boolean => {
|
|
153
|
+
if (!date) return true;
|
|
154
|
+
if (minDate && compareDates(date, minDate) < 0) return true;
|
|
155
|
+
if (maxDate && compareDates(date, maxDate) > 0) return true;
|
|
156
|
+
if (disabledDates?.some((d) => isSameDay(date, d))) return true;
|
|
157
|
+
return false;
|
|
158
|
+
},
|
|
159
|
+
[minDate, maxDate, disabledDates],
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const navigateMonth = useCallback((direction: 1 | -1) => {
|
|
163
|
+
setCurrentMonth((prev) => addMonths(prev, direction));
|
|
164
|
+
}, []);
|
|
165
|
+
|
|
166
|
+
// Handle date press for both single and range modes
|
|
167
|
+
const handleDatePress = useCallback(
|
|
168
|
+
(date: Date) => {
|
|
169
|
+
if (selectionMode === 'single' && singleOnChange) {
|
|
170
|
+
singleOnChange(date);
|
|
171
|
+
} else if (selectionMode === 'range' && rangeOnChange) {
|
|
172
|
+
// Range selection logic:
|
|
173
|
+
// 1. If no start date, set start date
|
|
174
|
+
// 2. If start date but no end date, set end date (if after start)
|
|
175
|
+
// 3. If both dates exist, reset to new start date
|
|
176
|
+
if (!rangeStart || (rangeStart && rangeEnd)) {
|
|
177
|
+
rangeOnChange({ startDate: date, endDate: null });
|
|
178
|
+
} else {
|
|
179
|
+
// Have start but no end
|
|
180
|
+
if (compareDates(date, rangeStart) < 0) {
|
|
181
|
+
// Clicked before start - make this the new start
|
|
182
|
+
rangeOnChange({ startDate: date, endDate: null });
|
|
183
|
+
} else if (isSameDay(date, rangeStart)) {
|
|
184
|
+
// Clicked same day - clear selection
|
|
185
|
+
rangeOnChange({ startDate: date, endDate: null });
|
|
186
|
+
} else {
|
|
187
|
+
// Clicked after start - set as end date
|
|
188
|
+
rangeOnChange({ startDate: rangeStart, endDate: date });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
[selectionMode, singleOnChange, rangeOnChange, rangeStart, rangeEnd],
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Check if date is in range (between start and end)
|
|
197
|
+
const isDateInRange = useCallback(
|
|
198
|
+
(date: Date | null): boolean => {
|
|
199
|
+
if (!date || selectionMode !== 'range' || !rangeStart || !rangeEnd) {
|
|
74
200
|
return false;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
201
|
+
}
|
|
202
|
+
return (
|
|
203
|
+
compareDates(date, rangeStart) > 0 && compareDates(date, rangeEnd) < 0
|
|
204
|
+
);
|
|
205
|
+
},
|
|
206
|
+
[selectionMode, rangeStart, rangeEnd],
|
|
207
|
+
);
|
|
78
208
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
209
|
+
const renderDay = useCallback(
|
|
210
|
+
({ item }: { item: Date | null }) => {
|
|
211
|
+
const isRangeStart =
|
|
212
|
+
selectionMode === 'range' && item && rangeStart
|
|
213
|
+
? isSameDay(item, rangeStart)
|
|
214
|
+
: false;
|
|
215
|
+
const isRangeEnd =
|
|
216
|
+
selectionMode === 'range' && item && rangeEnd
|
|
217
|
+
? isSameDay(item, rangeEnd)
|
|
218
|
+
: false;
|
|
219
|
+
const isSelected =
|
|
220
|
+
selectionMode === 'single' && item && singleValue
|
|
221
|
+
? isSameDay(item, singleValue)
|
|
222
|
+
: false;
|
|
82
223
|
|
|
83
|
-
|
|
84
|
-
({ item }: { item: Date | null }) => (
|
|
224
|
+
return (
|
|
85
225
|
<DayCell
|
|
86
226
|
date={item}
|
|
87
|
-
isSelected={
|
|
227
|
+
isSelected={isSelected}
|
|
88
228
|
isToday={item ? isSameDay(item, todayDate) : false}
|
|
89
229
|
isDisabled={isDisabled(item)}
|
|
90
230
|
isWeekend={
|
|
91
231
|
item ? getDayOfWeek(item) === 0 || getDayOfWeek(item) === 6 : false
|
|
92
232
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const keyExtractor = useCallback(
|
|
100
|
-
(item: Date | null, index: number) =>
|
|
101
|
-
item?.toISOString() ?? `empty-${index}`,
|
|
102
|
-
[],
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const getItemLayout = useCallback(
|
|
106
|
-
(_data: ArrayLike<Date | null> | null | undefined, index: number) => ({
|
|
107
|
-
length: CELL_SIZE,
|
|
108
|
-
offset: CELL_SIZE * Math.floor(index / 7),
|
|
109
|
-
index,
|
|
110
|
-
}),
|
|
111
|
-
[],
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<View style={styles.container}>
|
|
116
|
-
<View style={styles.header}>
|
|
117
|
-
<Pressable onPress={() => navigateMonth(-1)} style={styles.navButton}>
|
|
118
|
-
<Text style={styles.navText}>‹</Text>
|
|
119
|
-
</Pressable>
|
|
120
|
-
<Text style={styles.monthTitle}>{formatYearMonth(currentMonth)}</Text>
|
|
121
|
-
<Pressable onPress={() => navigateMonth(1)} style={styles.navButton}>
|
|
122
|
-
<Text style={styles.navText}>›</Text>
|
|
123
|
-
</Pressable>
|
|
124
|
-
</View>
|
|
125
|
-
|
|
126
|
-
<View style={styles.weekDays}>
|
|
127
|
-
{WEEK_DAYS.map((day) => (
|
|
128
|
-
<Text key={day} style={styles.weekDayText}>
|
|
129
|
-
{day}
|
|
130
|
-
</Text>
|
|
131
|
-
))}
|
|
132
|
-
</View>
|
|
133
|
-
|
|
134
|
-
<FlatList
|
|
135
|
-
data={days}
|
|
136
|
-
renderItem={renderDay}
|
|
137
|
-
keyExtractor={keyExtractor}
|
|
138
|
-
getItemLayout={getItemLayout}
|
|
139
|
-
numColumns={7}
|
|
140
|
-
scrollEnabled={false}
|
|
141
|
-
removeClippedSubviews={true}
|
|
142
|
-
maxToRenderPerBatch={14}
|
|
143
|
-
windowSize={3}
|
|
144
|
-
initialNumToRender={42}
|
|
233
|
+
isRangeStart={isRangeStart}
|
|
234
|
+
isRangeEnd={isRangeEnd}
|
|
235
|
+
isInRange={isDateInRange(item)}
|
|
236
|
+
onPress={
|
|
237
|
+
item && !isDisabled(item) ? () => handleDatePress(item) : undefined
|
|
238
|
+
}
|
|
145
239
|
/>
|
|
240
|
+
);
|
|
241
|
+
},
|
|
242
|
+
[
|
|
243
|
+
selectionMode,
|
|
244
|
+
singleValue,
|
|
245
|
+
rangeStart,
|
|
246
|
+
rangeEnd,
|
|
247
|
+
todayDate,
|
|
248
|
+
isDisabled,
|
|
249
|
+
isDateInRange,
|
|
250
|
+
handleDatePress,
|
|
251
|
+
],
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const keyExtractor = useCallback(
|
|
255
|
+
(item: Date | null, index: number) =>
|
|
256
|
+
item?.toISOString() ?? `empty-${index}`,
|
|
257
|
+
[],
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const getItemLayout = useCallback(
|
|
261
|
+
(_data: ArrayLike<Date | null> | null | undefined, index: number) => ({
|
|
262
|
+
length: CELL_SIZE,
|
|
263
|
+
offset: CELL_SIZE * Math.floor(index / 7),
|
|
264
|
+
index,
|
|
265
|
+
}),
|
|
266
|
+
[],
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// Build override styles from themeOverrides
|
|
270
|
+
const containerStyle = useMemo(
|
|
271
|
+
() => ({
|
|
272
|
+
backgroundColor: overrides?.backgroundColor ?? '#1E1E1E',
|
|
273
|
+
borderRadius: overrides?.borderRadius ?? 16,
|
|
274
|
+
padding: overrides?.padding ?? 16,
|
|
275
|
+
}),
|
|
276
|
+
[overrides],
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const navTextStyle = useMemo(
|
|
280
|
+
() => ({
|
|
281
|
+
color: overrides?.primaryColor ?? '#4DA6FF',
|
|
282
|
+
}),
|
|
283
|
+
[overrides],
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const monthTitleStyle = useMemo(
|
|
287
|
+
() => ({
|
|
288
|
+
color: overrides?.textColor ?? '#FFFFFF',
|
|
289
|
+
}),
|
|
290
|
+
[overrides],
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return (
|
|
294
|
+
<View style={[styles.container, containerStyle]}>
|
|
295
|
+
<View style={styles.header}>
|
|
296
|
+
<Pressable onPress={() => navigateMonth(-1)} style={styles.navButton}>
|
|
297
|
+
<Text style={[styles.navText, navTextStyle]}>‹</Text>
|
|
298
|
+
</Pressable>
|
|
299
|
+
<Text style={[styles.monthTitle, monthTitleStyle]}>
|
|
300
|
+
{formatYearMonth(currentMonth)}
|
|
301
|
+
</Text>
|
|
302
|
+
<Pressable onPress={() => navigateMonth(1)} style={styles.navButton}>
|
|
303
|
+
<Text style={[styles.navText, navTextStyle]}>›</Text>
|
|
304
|
+
</Pressable>
|
|
305
|
+
</View>
|
|
306
|
+
|
|
307
|
+
<View style={styles.weekDays}>
|
|
308
|
+
{weekDays.map((day) => (
|
|
309
|
+
<Text key={day} style={styles.weekDayText}>
|
|
310
|
+
{day}
|
|
311
|
+
</Text>
|
|
312
|
+
))}
|
|
146
313
|
</View>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
314
|
+
|
|
315
|
+
<FlatList
|
|
316
|
+
data={days}
|
|
317
|
+
renderItem={renderDay}
|
|
318
|
+
keyExtractor={keyExtractor}
|
|
319
|
+
getItemLayout={getItemLayout}
|
|
320
|
+
numColumns={7}
|
|
321
|
+
scrollEnabled={false}
|
|
322
|
+
removeClippedSubviews={true}
|
|
323
|
+
maxToRenderPerBatch={14}
|
|
324
|
+
windowSize={3}
|
|
325
|
+
initialNumToRender={42}
|
|
326
|
+
/>
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
});
|
|
150
330
|
|
|
151
331
|
CalendarGrid.displayName = 'CalendarGrid';
|