@idealyst/datepicker 1.1.3 → 1.1.5

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.
Files changed (80) hide show
  1. package/package.json +6 -5
  2. package/src/DateInput.native.tsx +155 -0
  3. package/src/DateInput.tsx +2 -0
  4. package/src/DateInput.web.tsx +146 -0
  5. package/src/DatePicker.tsx +276 -0
  6. package/src/DateTimePicker.tsx +89 -0
  7. package/src/TimeInput.native.tsx +175 -0
  8. package/src/TimeInput.tsx +2 -0
  9. package/src/TimeInput.web.tsx +171 -0
  10. package/src/TimePicker.tsx +106 -0
  11. package/src/examples/DatePickerExamples.tsx +113 -149
  12. package/src/examples/index.ts +1 -1
  13. package/src/index.native.ts +15 -20
  14. package/src/index.ts +14 -19
  15. package/src/styles.ts +127 -0
  16. package/src/types.ts +56 -0
  17. package/src/DateInput/DateInput.native.tsx +0 -61
  18. package/src/DateInput/DateInput.styles.tsx +0 -26
  19. package/src/DateInput/DateInput.web.tsx +0 -61
  20. package/src/DateInput/DateInputBase.tsx +0 -228
  21. package/src/DateInput/index.native.ts +0 -2
  22. package/src/DateInput/index.ts +0 -2
  23. package/src/DateInput/types.ts +0 -60
  24. package/src/DatePicker/Calendar.native.tsx +0 -261
  25. package/src/DatePicker/Calendar.styles.tsx +0 -230
  26. package/src/DatePicker/Calendar.web.tsx +0 -159
  27. package/src/DatePicker/DatePicker.native.tsx +0 -51
  28. package/src/DatePicker/DatePicker.styles.tsx +0 -76
  29. package/src/DatePicker/DatePicker.web.tsx +0 -31
  30. package/src/DatePicker/index.native.ts +0 -3
  31. package/src/DatePicker/index.ts +0 -3
  32. package/src/DatePicker/types.ts +0 -78
  33. package/src/DateRangePicker/DateRangePicker.native.tsx +0 -39
  34. package/src/DateRangePicker/DateRangePicker.styles.tsx +0 -83
  35. package/src/DateRangePicker/DateRangePicker.web.tsx +0 -40
  36. package/src/DateRangePicker/RangeCalendar.native.tsx +0 -355
  37. package/src/DateRangePicker/RangeCalendar.styles.tsx +0 -200
  38. package/src/DateRangePicker/RangeCalendar.web.tsx +0 -384
  39. package/src/DateRangePicker/index.native.ts +0 -3
  40. package/src/DateRangePicker/index.ts +0 -3
  41. package/src/DateRangePicker/types.ts +0 -107
  42. package/src/DateTimePicker/DateTimePicker.native.tsx +0 -24
  43. package/src/DateTimePicker/DateTimePicker.styles.tsx +0 -104
  44. package/src/DateTimePicker/DateTimePicker.tsx +0 -21
  45. package/src/DateTimePicker/DateTimePickerBase.tsx +0 -185
  46. package/src/DateTimePicker/TimePicker.native.tsx +0 -17
  47. package/src/DateTimePicker/TimePicker.styles.tsx +0 -115
  48. package/src/DateTimePicker/TimePicker.tsx +0 -14
  49. package/src/DateTimePicker/TimePickerBase.tsx +0 -232
  50. package/src/DateTimePicker/index.native.ts +0 -3
  51. package/src/DateTimePicker/index.ts +0 -3
  52. package/src/DateTimePicker/primitives/ClockFace.native.tsx +0 -195
  53. package/src/DateTimePicker/primitives/ClockFace.web.tsx +0 -168
  54. package/src/DateTimePicker/primitives/TimeInput.native.tsx +0 -53
  55. package/src/DateTimePicker/primitives/TimeInput.web.tsx +0 -66
  56. package/src/DateTimePicker/primitives/index.native.ts +0 -2
  57. package/src/DateTimePicker/primitives/index.ts +0 -2
  58. package/src/DateTimePicker/primitives/index.web.ts +0 -2
  59. package/src/DateTimePicker/types.ts +0 -80
  60. package/src/DateTimePicker/utils/dimensions.native.ts +0 -9
  61. package/src/DateTimePicker/utils/dimensions.ts +0 -9
  62. package/src/DateTimePicker/utils/dimensions.web.ts +0 -33
  63. package/src/DateTimeRangePicker/DateTimeRangePicker.native.tsx +0 -24
  64. package/src/DateTimeRangePicker/DateTimeRangePicker.styles.tsx +0 -118
  65. package/src/DateTimeRangePicker/DateTimeRangePicker.web.tsx +0 -21
  66. package/src/DateTimeRangePicker/DateTimeRangePickerBase.tsx +0 -327
  67. package/src/DateTimeRangePicker/index.native.ts +0 -2
  68. package/src/DateTimeRangePicker/index.ts +0 -2
  69. package/src/DateTimeRangePicker/types.ts +0 -70
  70. package/src/primitives/CalendarGrid/CalendarGrid.styles.tsx +0 -51
  71. package/src/primitives/CalendarGrid/CalendarGrid.tsx +0 -146
  72. package/src/primitives/CalendarGrid/index.ts +0 -1
  73. package/src/primitives/CalendarHeader/CalendarHeader.styles.tsx +0 -25
  74. package/src/primitives/CalendarHeader/CalendarHeader.tsx +0 -69
  75. package/src/primitives/CalendarHeader/index.ts +0 -1
  76. package/src/primitives/CalendarOverlay/CalendarOverlay.styles.tsx +0 -86
  77. package/src/primitives/CalendarOverlay/CalendarOverlay.tsx +0 -136
  78. package/src/primitives/CalendarOverlay/index.ts +0 -1
  79. package/src/primitives/Wrapper/Wrapper.web.tsx +0 -33
  80. package/src/primitives/Wrapper/index.ts +0 -1
@@ -1,83 +0,0 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
-
3
- export const dateRangePickerStyles = StyleSheet.create((theme) => ({
4
- container: {
5
- gap: theme.spacing?.md || 16,
6
- },
7
-
8
- label: {
9
- fontSize: theme.typography?.fontSize?.sm || 14,
10
- fontWeight: '600',
11
- color: theme.colors?.text?.primary || '#111827',
12
- marginBottom: theme.spacing?.xs || 4,
13
- },
14
-
15
- picker: {
16
- gap: theme.spacing?.md || 16,
17
- },
18
-
19
- selectedRangeHeader: {
20
- padding: theme.spacing?.sm || 12,
21
- backgroundColor: theme.colors?.surface?.secondary || '#f9fafb',
22
- borderRadius: theme.borderRadius?.md || 8,
23
- borderWidth: 1,
24
- borderColor: theme.colors?.border?.primary || '#e5e7eb',
25
- gap: theme.spacing?.xs || 4,
26
-
27
- _web: {
28
- border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
29
- },
30
- },
31
-
32
- selectedRangeLabel: {
33
- fontSize: theme.typography?.fontSize?.sm || 12,
34
- fontWeight: '500',
35
- color: theme.colors?.text?.secondary || '#6b7280',
36
- },
37
-
38
- selectedRangeValue: {
39
- fontSize: theme.typography?.fontSize?.md || 16,
40
- fontWeight: '600',
41
- color: theme.colors?.text?.primary || '#111827',
42
- },
43
-
44
- rangeInputs: {
45
- flexDirection: 'row',
46
- alignItems: 'center',
47
- gap: theme.spacing?.sm || 12,
48
- },
49
-
50
- rangeInput: {
51
- flex: 1,
52
- padding: theme.spacing?.sm || 12,
53
- borderWidth: 1,
54
- borderColor: theme.colors?.border?.primary || '#e5e7eb',
55
- borderRadius: theme.borderRadius?.md || 8,
56
- backgroundColor: theme.colors?.surface?.primary || '#ffffff',
57
- fontSize: theme.typography?.fontSize?.md || 16,
58
- textAlign: 'center',
59
-
60
- _web: {
61
- border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
62
- outline: 'none',
63
- },
64
- },
65
-
66
- rangeSeparator: {
67
- fontSize: theme.typography?.fontSize?.md || 16,
68
- fontWeight: '500',
69
- color: theme.colors?.text?.secondary || '#6b7280',
70
- },
71
-
72
- errorText: {
73
- fontSize: theme.typography?.fontSize?.sm || 12,
74
- color: theme.colors?.semantic?.error || '#dc2626',
75
- marginTop: theme.spacing?.xs || 4,
76
- },
77
-
78
- helperText: {
79
- fontSize: theme.typography?.fontSize?.sm || 12,
80
- color: theme.colors?.text?.secondary || '#6b7280',
81
- marginTop: theme.spacing?.xs || 4,
82
- },
83
- }));
@@ -1,40 +0,0 @@
1
- import React from 'react';
2
- import { View, Text } from '@idealyst/components';
3
- import { getWebProps } from 'react-native-unistyles/web';
4
- import { DateRangePickerProps, DateRange } from './types';
5
- import { RangeCalendar } from './RangeCalendar.web';
6
- import { dateRangePickerStyles } from './DateRangePicker.styles';
7
-
8
- const DateRangePicker: React.FC<DateRangePickerProps> = ({
9
- value,
10
- onChange,
11
- minDate,
12
- maxDate,
13
- disabled = false,
14
- allowSameDay = true,
15
- maxDays,
16
- style,
17
- testID,
18
- }) => {
19
-
20
- const handleRangeChange = (newRange: DateRange) => {
21
- onChange(newRange.startDate || newRange.endDate ? newRange : null);
22
- };
23
-
24
-
25
- return (
26
- <RangeCalendar
27
- value={value || {}}
28
- onChange={handleRangeChange}
29
- minDate={minDate}
30
- maxDate={maxDate}
31
- disabled={disabled}
32
- allowSameDay={allowSameDay}
33
- maxDays={maxDays}
34
- style={style}
35
- testID={testID}
36
- />
37
- );
38
- };
39
-
40
- export default DateRangePicker;
@@ -1,355 +0,0 @@
1
- import React, { useState, useMemo } from 'react';
2
- import { View, Text, Button } from '@idealyst/components';
3
- import { TouchableOpacity } from 'react-native';
4
- import { RangeCalendarProps, DateRange } from './types';
5
- import { rangeCalendarStyles } from './RangeCalendar.styles';
6
- import { CalendarOverlay } from '../primitives/CalendarOverlay';
7
-
8
- export const RangeCalendar: React.FC<RangeCalendarProps> = ({
9
- value = {},
10
- onChange,
11
- onDateSelected,
12
- showTimes = false,
13
- timeMode = '12h',
14
- minDate,
15
- maxDate,
16
- disabled = false,
17
- currentMonth: controlledCurrentMonth,
18
- onMonthChange,
19
- allowSameDay = true,
20
- maxDays,
21
- style,
22
- testID,
23
- }) => {
24
- const [internalCurrentMonth, setInternalCurrentMonth] = useState(
25
- controlledCurrentMonth || value?.startDate || new Date()
26
- );
27
- const [selectingEnd, setSelectingEnd] = useState(false);
28
- const [overlayMode, setOverlayMode] = useState<'month' | 'year' | null>(null);
29
-
30
- const currentMonth = controlledCurrentMonth || internalCurrentMonth;
31
-
32
- const handleMonthChange = (newMonth: Date) => {
33
- if (onMonthChange) {
34
- onMonthChange(newMonth);
35
- } else {
36
- setInternalCurrentMonth(newMonth);
37
- }
38
- };
39
-
40
- const { monthStart, monthEnd, daysInMonth, startingDayOfWeek } = useMemo(() => {
41
- const monthStart = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), 1);
42
- const monthEnd = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 0);
43
- const daysInMonth = monthEnd.getDate();
44
- const startingDayOfWeek = monthStart.getDay();
45
-
46
- return { monthStart, monthEnd, daysInMonth, startingDayOfWeek };
47
- }, [currentMonth]);
48
-
49
- const isDateDisabled = (date: Date): boolean => {
50
- if (disabled) return true;
51
- if (minDate && date < minDate) return true;
52
- if (maxDate && date > maxDate) return true;
53
- return false;
54
- };
55
-
56
- const isDateInRange = (date: Date): boolean => {
57
- const { startDate, endDate } = value || {};
58
- if (!startDate || !endDate) return false;
59
- return date > startDate && date < endDate;
60
- };
61
-
62
- const isDateRangeStart = (date: Date): boolean => {
63
- const { startDate } = value || {};
64
- if (!startDate) return false;
65
- return (
66
- date.getDate() === startDate.getDate() &&
67
- date.getMonth() === startDate.getMonth() &&
68
- date.getFullYear() === startDate.getFullYear()
69
- );
70
- };
71
-
72
- const isDateRangeEnd = (date: Date): boolean => {
73
- const { endDate } = value || {};
74
- if (!endDate) return false;
75
- return (
76
- date.getDate() === endDate.getDate() &&
77
- date.getMonth() === endDate.getMonth() &&
78
- date.getFullYear() === endDate.getFullYear()
79
- );
80
- };
81
-
82
- const isDateSelected = (date: Date): boolean => {
83
- return isDateRangeStart(date) || isDateRangeEnd(date);
84
- };
85
-
86
- const formatTime = (date: Date): string => {
87
- let hours = date.getHours();
88
- const minutes = String(date.getMinutes()).padStart(2, '0');
89
-
90
- if (timeMode === '12h') {
91
- const ampm = hours >= 12 ? 'PM' : 'AM';
92
- hours = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
93
- return `${hours}:${minutes}${ampm}`;
94
- } else {
95
- return `${String(hours).padStart(2, '0')}:${minutes}`;
96
- }
97
- };
98
-
99
- const getDateTimeInfo = (date: Date) => {
100
- if (!showTimes) return null;
101
-
102
- const isStart = isDateRangeStart(date);
103
- const isEnd = isDateRangeEnd(date);
104
-
105
- if (isStart && value?.startDate) {
106
- return { type: 'start', time: formatTime(value.startDate) };
107
- }
108
- if (isEnd && value?.endDate) {
109
- return { type: 'end', time: formatTime(value.endDate) };
110
- }
111
- return null;
112
- };
113
-
114
- const handleDateClick = (date: Date) => {
115
- if (isDateDisabled(date)) return;
116
-
117
- const { startDate, endDate } = value || {};
118
-
119
- // If no range is selected or we're starting fresh
120
- if (!startDate || (startDate && endDate)) {
121
- onChange({ startDate: date, endDate: undefined });
122
- setSelectingEnd(true);
123
- onDateSelected?.('start');
124
- return;
125
- }
126
-
127
- // If we have a start date but no end date
128
- if (startDate && !endDate) {
129
- let newStartDate = startDate;
130
- let newEndDate = date;
131
-
132
- // Swap if end date is before start date
133
- if (date < startDate) {
134
- newStartDate = date;
135
- newEndDate = startDate;
136
- }
137
-
138
- // Check if same day selection is allowed
139
- if (!allowSameDay && newStartDate.getTime() === newEndDate.getTime()) {
140
- return;
141
- }
142
-
143
- // Check max days constraint
144
- if (maxDays) {
145
- const daysDiff = Math.ceil((newEndDate.getTime() - newStartDate.getTime()) / (1000 * 60 * 60 * 24));
146
- if (daysDiff > maxDays) {
147
- return;
148
- }
149
- }
150
-
151
- onChange({ startDate: newStartDate, endDate: newEndDate });
152
- setSelectingEnd(false);
153
- onDateSelected?.('end');
154
- }
155
- };
156
-
157
- const goToPreviousMonth = () => {
158
- const newMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1);
159
- handleMonthChange(newMonth);
160
- };
161
-
162
- const goToNextMonth = () => {
163
- const newMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1);
164
- handleMonthChange(newMonth);
165
- };
166
-
167
- const createDateWithDayAdjustment = (year: number, month: number, day: number): Date => {
168
- // Get the last day of the target month
169
- const lastDayOfMonth = new Date(year, month + 1, 0).getDate();
170
- // Use the smaller of the requested day or the last day of the month
171
- const adjustedDay = Math.min(day, lastDayOfMonth);
172
- return new Date(year, month, adjustedDay);
173
- };
174
-
175
- const handleMonthSelect = (monthIndex: number) => {
176
- const newMonth = new Date(currentMonth.getFullYear(), monthIndex, 1);
177
- handleMonthChange(newMonth);
178
- setOverlayMode(null);
179
- };
180
-
181
- const handleYearSelect = (year: number) => {
182
- const newMonth = new Date(year, currentMonth.getMonth(), 1);
183
- handleMonthChange(newMonth);
184
- setOverlayMode(null);
185
- };
186
-
187
-
188
- const monthName = currentMonth.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
189
-
190
- // Create calendar grid
191
- const calendarDays = [];
192
-
193
- // Add previous month days to fill start of week
194
- const prevMonthEnd = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), 0);
195
- const prevMonthDaysToShow = startingDayOfWeek;
196
- for (let i = prevMonthDaysToShow - 1; i >= 0; i--) {
197
- const day = prevMonthEnd.getDate() - i;
198
- const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, day);
199
- calendarDays.push({ date, isCurrentMonth: false });
200
- }
201
-
202
- // Add days of the current month
203
- for (let day = 1; day <= daysInMonth; day++) {
204
- const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day);
205
- calendarDays.push({ date, isCurrentMonth: true });
206
- }
207
-
208
- // Add next month days to complete partial weeks
209
- const currentLength = calendarDays.length;
210
- const weeksNeeded = Math.ceil(currentLength / 7);
211
- const totalCalendarDays = weeksNeeded * 7;
212
-
213
- const remainingDays = totalCalendarDays - currentLength;
214
- for (let day = 1; day <= remainingDays; day++) {
215
- const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, day);
216
- calendarDays.push({ date, isCurrentMonth: false });
217
- }
218
-
219
- rangeCalendarStyles.useVariants({});
220
-
221
- return (
222
- <View style={[rangeCalendarStyles.container, style]} testID={testID}>
223
- {/* Header */}
224
- <View style={rangeCalendarStyles.header}>
225
- <Button
226
- type="text"
227
- size="sm"
228
- onPress={goToPreviousMonth}
229
- disabled={disabled}
230
- style={rangeCalendarStyles.headerButton}
231
- >
232
-
233
- </Button>
234
- <View style={rangeCalendarStyles.headerTitle}>
235
- <Button
236
- type="text"
237
- size="sm"
238
- onPress={() => setOverlayMode('month')}
239
- disabled={disabled}
240
- style={rangeCalendarStyles.compactButton}
241
- >
242
- <Text weight="semibold">{currentMonth.toLocaleDateString('en-US', { month: 'long' })}</Text>
243
- </Button>
244
- <Button
245
- type="text"
246
- size="sm"
247
- onPress={() => setOverlayMode('year')}
248
- disabled={disabled}
249
- style={rangeCalendarStyles.compactButton}
250
- >
251
- <Text weight="semibold">{currentMonth.getFullYear()}</Text>
252
- </Button>
253
- </View>
254
- <Button
255
- type="text"
256
- size="sm"
257
- onPress={goToNextMonth}
258
- disabled={disabled}
259
- style={rangeCalendarStyles.headerButton}
260
- >
261
-
262
- </Button>
263
- </View>
264
-
265
- {/* Weekday headers */}
266
- <View style={rangeCalendarStyles.weekdayHeader}>
267
- {['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((day) => (
268
- <View key={day} style={rangeCalendarStyles.weekdayCell}>
269
- <Text style={rangeCalendarStyles.weekdayText}>
270
- {day}
271
- </Text>
272
- </View>
273
- ))}
274
- </View>
275
-
276
- {/* Calendar grid */}
277
- <View style={rangeCalendarStyles.calendarGrid}>
278
- {calendarDays.map((dayInfo, index) => (
279
- <View key={index} style={rangeCalendarStyles.dayCell}>
280
- {dayInfo && (
281
- <TouchableOpacity
282
- onPress={() => handleDateClick(dayInfo.date)}
283
- disabled={isDateDisabled(dayInfo.date)}
284
- style={[
285
- rangeCalendarStyles.dayButton,
286
- {
287
- backgroundColor: isDateSelected(dayInfo.date)
288
- ? '#3b82f6'
289
- : isDateInRange(dayInfo.date)
290
- ? '#3b82f620'
291
- : 'transparent',
292
- opacity: isDateDisabled(dayInfo.date) ? 0.5 : dayInfo.isCurrentMonth ? 1 : 0.5,
293
- flexDirection: 'column',
294
- justifyContent: 'center',
295
- alignItems: 'center',
296
- position: 'relative',
297
- flex: 1,
298
- aspectRatio: 1,
299
- }
300
- ]}
301
- >
302
- <Text
303
- style={{
304
- color: isDateSelected(dayInfo.date) ? 'white' : dayInfo.isCurrentMonth ? 'black' : '#9ca3af',
305
- fontSize: 13,
306
- fontWeight: isDateSelected(dayInfo.date) ? '600' : '400',
307
- textAlign: 'center',
308
- }}
309
- >
310
- {dayInfo.date.getDate()}
311
- </Text>
312
- {(() => {
313
- const timeInfo = getDateTimeInfo(dayInfo.date);
314
- if (timeInfo) {
315
- return (
316
- <Text
317
- style={{
318
- color: isDateSelected(dayInfo.date) ? 'white' : '#666',
319
- fontSize: 7,
320
- fontWeight: '500',
321
- textAlign: 'center',
322
- marginTop: 1,
323
- width: '100%',
324
- }}
325
- numberOfLines={1}
326
- ellipsizeMode="tail"
327
- >
328
- {timeInfo.time}
329
- </Text>
330
- );
331
- }
332
- return null;
333
- })()}
334
- </TouchableOpacity>
335
- )}
336
- </View>
337
- ))}
338
- </View>
339
-
340
- {/* Overlay for month/year selection */}
341
- {overlayMode && (
342
- <CalendarOverlay
343
- mode={overlayMode}
344
- currentMonth={currentMonth.getMonth()}
345
- currentYear={currentMonth.getFullYear()}
346
- onMonthSelect={handleMonthSelect}
347
- onYearSelect={handleYearSelect}
348
- onClose={() => setOverlayMode(null)}
349
- disabled={disabled}
350
- />
351
- )}
352
-
353
- </View>
354
- );
355
- };
@@ -1,200 +0,0 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
-
3
- export const rangeCalendarStyles = StyleSheet.create((theme) => ({
4
- container: {
5
- width: 256,
6
- position: 'relative',
7
- },
8
-
9
- header: {
10
- flexDirection: 'row',
11
- justifyContent: 'space-between',
12
- alignItems: 'center',
13
- marginBottom: theme.spacing?.md || 16,
14
-
15
- _web: {
16
- display: 'flex',
17
- },
18
- },
19
-
20
- headerButton: {
21
- minWidth: 32,
22
- minHeight: 32,
23
- paddingHorizontal: theme.spacing?.xs || 8,
24
- paddingVertical: theme.spacing?.xs || 4,
25
- },
26
-
27
- headerTitle: {
28
- flexDirection: 'row',
29
- alignItems: 'center',
30
- gap: theme.spacing?.xs || 8,
31
- },
32
-
33
- monthYearButton: {
34
- paddingHorizontal: theme.spacing?.sm || 8,
35
- paddingVertical: theme.spacing?.xs || 4,
36
- },
37
-
38
- weekdayHeader: {
39
- flexDirection: 'row',
40
- marginBottom: theme.spacing?.xs || 8,
41
-
42
- // Web specific styles
43
- _web: {
44
- display: 'grid',
45
- gridTemplateColumns: 'repeat(7, 1fr)',
46
- gap: 2,
47
- flexDirection: undefined,
48
- },
49
- },
50
-
51
- weekdayCell: {
52
- flex: 1,
53
- width: 36,
54
- minWidth: 36,
55
- maxWidth: 36,
56
- alignItems: 'center',
57
- justifyContent: 'center',
58
- paddingVertical: theme.spacing?.xs || 4,
59
-
60
- // Web specific styles
61
- _web: {
62
- display: 'flex',
63
- flex: undefined,
64
- width: '36px',
65
- minWidth: '36px',
66
- maxWidth: '36px',
67
- },
68
- },
69
-
70
- weekdayText: {
71
- fontSize: theme.typography?.fontSize?.sm || 12,
72
- fontWeight: '500',
73
- color: theme.colors?.text?.secondary || '#6b7280',
74
- },
75
-
76
- calendarGrid: {
77
- flexDirection: 'row',
78
- flexWrap: 'wrap',
79
- marginBottom: theme.spacing?.xs || 8,
80
-
81
- // Web specific styles
82
- _web: {
83
- display: 'grid',
84
- gridTemplateColumns: 'repeat(7, 1fr)',
85
- gap: 2,
86
- flexDirection: undefined,
87
- flexWrap: undefined,
88
- },
89
- },
90
-
91
- dayCell: {
92
- width: '14.28%', // 100% / 7 days
93
- minWidth: 36,
94
- maxWidth: 36,
95
- aspectRatio: 1,
96
- alignItems: 'stretch',
97
- justifyContent: 'stretch',
98
- height: 36,
99
- maxHeight: 36,
100
-
101
- // Web specific styles
102
- _web: {
103
- display: 'flex',
104
- width: '36px',
105
- minWidth: '36px',
106
- maxWidth: '36px',
107
- height: '36px',
108
- maxHeight: '36px',
109
- },
110
- },
111
-
112
- dayButton: {
113
- flex: 1,
114
- width: '100%',
115
- height: '100%',
116
- minWidth: 36,
117
- maxWidth: 36,
118
- minHeight: 36,
119
- maxHeight: 36,
120
- padding: 0,
121
- margin: 0,
122
- borderRadius: theme.borderRadius?.sm || 6,
123
- fontSize: theme.typography?.fontSize?.sm || 13,
124
- alignItems: 'center',
125
- justifyContent: 'center',
126
- overflow: 'hidden',
127
-
128
- variants: {
129
- inRange: {
130
- true: {
131
- backgroundColor: theme.colors?.accent?.primary + '20' || '#3b82f620',
132
- borderRadius: 0,
133
- },
134
- false: {},
135
- },
136
- isStart: {
137
- true: {
138
- backgroundColor: theme.colors?.accent?.primary || '#3b82f6',
139
- borderTopLeftRadius: theme.borderRadius?.sm || 6,
140
- borderBottomLeftRadius: theme.borderRadius?.sm || 6,
141
- },
142
- false: {},
143
- },
144
- isEnd: {
145
- true: {
146
- backgroundColor: theme.colors?.accent?.primary || '#3b82f6',
147
- borderTopRightRadius: theme.borderRadius?.sm || 6,
148
- borderBottomRightRadius: theme.borderRadius?.sm || 6,
149
- },
150
- false: {},
151
- },
152
- isSelected: {
153
- true: {
154
- backgroundColor: theme.colors?.accent?.primary || '#3b82f6',
155
- fontWeight: '600',
156
- },
157
- false: {
158
- fontWeight: '400',
159
- },
160
- },
161
- },
162
-
163
- // Web specific styling
164
- _web: {
165
- width: '36px',
166
- height: '36px',
167
- minWidth: '36px',
168
- maxWidth: '36px',
169
- minHeight: '36px',
170
- maxHeight: '36px',
171
- display: 'flex',
172
- overflow: 'hidden',
173
- },
174
- },
175
-
176
- rangePresets: {
177
- paddingTop: theme.spacing?.sm || 12,
178
- borderTopWidth: 1,
179
- borderTopColor: theme.colors?.border?.secondary || '#f3f4f6',
180
- gap: theme.spacing?.xs || 8,
181
-
182
- // Web specific border
183
- _web: {
184
- borderTop: `1px solid ${theme.colors?.border?.secondary || '#f3f4f6'}`,
185
- },
186
- },
187
-
188
- presetButton: {
189
- width: '100%',
190
- justifyContent: 'flex-start',
191
- },
192
-
193
- clearButton: {
194
- width: '100%',
195
- },
196
-
197
- compactButton: {
198
- padding: 4,
199
- },
200
- }));