@idealyst/datepicker 1.1.4 → 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.
- package/package.json +6 -5
- package/src/DateInput.native.tsx +155 -0
- package/src/DateInput.tsx +2 -0
- package/src/DateInput.web.tsx +146 -0
- package/src/DatePicker.tsx +276 -0
- package/src/DateTimePicker.tsx +89 -0
- package/src/TimeInput.native.tsx +175 -0
- package/src/TimeInput.tsx +2 -0
- package/src/TimeInput.web.tsx +171 -0
- package/src/TimePicker.tsx +106 -0
- package/src/examples/DatePickerExamples.tsx +113 -149
- package/src/examples/index.ts +1 -1
- package/src/index.native.ts +15 -20
- package/src/index.ts +14 -19
- package/src/styles.ts +127 -0
- package/src/types.ts +56 -0
- package/src/DateInput/DateInput.native.tsx +0 -61
- package/src/DateInput/DateInput.styles.tsx +0 -26
- package/src/DateInput/DateInput.web.tsx +0 -61
- package/src/DateInput/DateInputBase.tsx +0 -228
- package/src/DateInput/index.native.ts +0 -2
- package/src/DateInput/index.ts +0 -2
- package/src/DateInput/types.ts +0 -60
- package/src/DatePicker/Calendar.native.tsx +0 -261
- package/src/DatePicker/Calendar.styles.tsx +0 -230
- package/src/DatePicker/Calendar.web.tsx +0 -159
- package/src/DatePicker/DatePicker.native.tsx +0 -51
- package/src/DatePicker/DatePicker.styles.tsx +0 -76
- package/src/DatePicker/DatePicker.web.tsx +0 -31
- package/src/DatePicker/index.native.ts +0 -3
- package/src/DatePicker/index.ts +0 -3
- package/src/DatePicker/types.ts +0 -78
- package/src/DateRangePicker/DateRangePicker.native.tsx +0 -39
- package/src/DateRangePicker/DateRangePicker.styles.tsx +0 -83
- package/src/DateRangePicker/DateRangePicker.web.tsx +0 -40
- package/src/DateRangePicker/RangeCalendar.native.tsx +0 -355
- package/src/DateRangePicker/RangeCalendar.styles.tsx +0 -200
- package/src/DateRangePicker/RangeCalendar.web.tsx +0 -384
- package/src/DateRangePicker/index.native.ts +0 -3
- package/src/DateRangePicker/index.ts +0 -3
- package/src/DateRangePicker/types.ts +0 -107
- package/src/DateTimePicker/DateTimePicker.native.tsx +0 -24
- package/src/DateTimePicker/DateTimePicker.styles.tsx +0 -104
- package/src/DateTimePicker/DateTimePicker.tsx +0 -21
- package/src/DateTimePicker/DateTimePickerBase.tsx +0 -185
- package/src/DateTimePicker/TimePicker.native.tsx +0 -17
- package/src/DateTimePicker/TimePicker.styles.tsx +0 -115
- package/src/DateTimePicker/TimePicker.tsx +0 -14
- package/src/DateTimePicker/TimePickerBase.tsx +0 -232
- package/src/DateTimePicker/index.native.ts +0 -3
- package/src/DateTimePicker/index.ts +0 -3
- package/src/DateTimePicker/primitives/ClockFace.native.tsx +0 -195
- package/src/DateTimePicker/primitives/ClockFace.web.tsx +0 -168
- package/src/DateTimePicker/primitives/TimeInput.native.tsx +0 -53
- package/src/DateTimePicker/primitives/TimeInput.web.tsx +0 -66
- package/src/DateTimePicker/primitives/index.native.ts +0 -2
- package/src/DateTimePicker/primitives/index.ts +0 -2
- package/src/DateTimePicker/primitives/index.web.ts +0 -2
- package/src/DateTimePicker/types.ts +0 -80
- package/src/DateTimePicker/utils/dimensions.native.ts +0 -9
- package/src/DateTimePicker/utils/dimensions.ts +0 -9
- package/src/DateTimePicker/utils/dimensions.web.ts +0 -33
- package/src/DateTimeRangePicker/DateTimeRangePicker.native.tsx +0 -24
- package/src/DateTimeRangePicker/DateTimeRangePicker.styles.tsx +0 -118
- package/src/DateTimeRangePicker/DateTimeRangePicker.web.tsx +0 -21
- package/src/DateTimeRangePicker/DateTimeRangePickerBase.tsx +0 -327
- package/src/DateTimeRangePicker/index.native.ts +0 -2
- package/src/DateTimeRangePicker/index.ts +0 -2
- package/src/DateTimeRangePicker/types.ts +0 -70
- package/src/primitives/CalendarGrid/CalendarGrid.styles.tsx +0 -51
- package/src/primitives/CalendarGrid/CalendarGrid.tsx +0 -146
- package/src/primitives/CalendarGrid/index.ts +0 -1
- package/src/primitives/CalendarHeader/CalendarHeader.styles.tsx +0 -25
- package/src/primitives/CalendarHeader/CalendarHeader.tsx +0 -69
- package/src/primitives/CalendarHeader/index.ts +0 -1
- package/src/primitives/CalendarOverlay/CalendarOverlay.styles.tsx +0 -86
- package/src/primitives/CalendarOverlay/CalendarOverlay.tsx +0 -136
- package/src/primitives/CalendarOverlay/index.ts +0 -1
- package/src/primitives/Wrapper/Wrapper.web.tsx +0 -33
- package/src/primitives/Wrapper/index.ts +0 -1
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { AppTheme } from '@idealyst/theme';
|
|
2
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
-
|
|
4
|
-
export const calendarStyles = StyleSheet.create((theme: AppTheme) => ({
|
|
5
|
-
container: {
|
|
6
|
-
width: 256,
|
|
7
|
-
_web: {
|
|
8
|
-
position: 'relative',
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
header: {
|
|
13
|
-
display: 'flex',
|
|
14
|
-
flexDirection: 'row',
|
|
15
|
-
justifyContent: 'space-between',
|
|
16
|
-
alignItems: 'center',
|
|
17
|
-
marginBottom: 16,
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
headerButton: {
|
|
21
|
-
minWidth: 32,
|
|
22
|
-
minHeight: 32,
|
|
23
|
-
paddingHorizontal: 8,
|
|
24
|
-
paddingVertical: 4,
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
headerTitle: {
|
|
28
|
-
display: 'flex',
|
|
29
|
-
flexDirection: 'row',
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
gap: 8,
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
monthYearButton: {
|
|
35
|
-
paddingHorizontal: 8,
|
|
36
|
-
paddingVertical: 4,
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
pickerContainer: {
|
|
40
|
-
marginBottom: 16,
|
|
41
|
-
padding: 12,
|
|
42
|
-
backgroundColor: theme.colors?.surface?.secondary || '#f9fafb',
|
|
43
|
-
borderRadius: 8,
|
|
44
|
-
borderWidth: 1,
|
|
45
|
-
borderColor: theme.colors?.border?.primary || '#e5e7eb',
|
|
46
|
-
|
|
47
|
-
// Web specific styles
|
|
48
|
-
_web: {
|
|
49
|
-
border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
|
|
50
|
-
borderWidth: undefined,
|
|
51
|
-
borderColor: undefined,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
monthPickerGrid: {
|
|
56
|
-
flexDirection: 'row',
|
|
57
|
-
flexWrap: 'wrap',
|
|
58
|
-
justifyContent: 'space-between',
|
|
59
|
-
width: '100%',
|
|
60
|
-
|
|
61
|
-
// Web specific styles
|
|
62
|
-
_web: {
|
|
63
|
-
display: 'flex',
|
|
64
|
-
gap: 6,
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
yearPickerGrid: {
|
|
69
|
-
flexDirection: 'row',
|
|
70
|
-
flexWrap: 'wrap',
|
|
71
|
-
justifyContent: 'space-between',
|
|
72
|
-
maxHeight: 200,
|
|
73
|
-
width: '100%',
|
|
74
|
-
|
|
75
|
-
// Web specific styles
|
|
76
|
-
_web: {
|
|
77
|
-
display: 'flex',
|
|
78
|
-
gap: 4,
|
|
79
|
-
overflowY: 'auto',
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
pickerButton: {
|
|
84
|
-
fontSize: 12,
|
|
85
|
-
paddingHorizontal: 6,
|
|
86
|
-
paddingVertical: 4,
|
|
87
|
-
minHeight: 32,
|
|
88
|
-
justifyContent: 'center',
|
|
89
|
-
alignItems: 'center',
|
|
90
|
-
width: '30%',
|
|
91
|
-
marginBottom: 4,
|
|
92
|
-
|
|
93
|
-
// Month buttons: 3 per row with equal spacing
|
|
94
|
-
variants: {
|
|
95
|
-
monthButton: {
|
|
96
|
-
true: {
|
|
97
|
-
_web: {
|
|
98
|
-
flex: '1 0 30%',
|
|
99
|
-
maxWidth: 'calc(33.333% - 4px)',
|
|
100
|
-
width: undefined,
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
yearButton: {
|
|
105
|
-
true: {
|
|
106
|
-
_web: {
|
|
107
|
-
flex: '1 0 22%',
|
|
108
|
-
maxWidth: 'calc(25% - 3px)',
|
|
109
|
-
width: undefined,
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
// Web specific styles
|
|
116
|
-
_web: {
|
|
117
|
-
display: 'flex',
|
|
118
|
-
width: undefined,
|
|
119
|
-
marginBottom: undefined,
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
weekdayHeader: {
|
|
124
|
-
flexDirection: 'row',
|
|
125
|
-
marginBottom: 8,
|
|
126
|
-
|
|
127
|
-
// Web specific styles
|
|
128
|
-
_web: {
|
|
129
|
-
display: 'grid',
|
|
130
|
-
gridTemplateColumns: 'repeat(7, 1fr)',
|
|
131
|
-
gap: 2,
|
|
132
|
-
flexDirection: undefined,
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
weekdayCell: {
|
|
137
|
-
flex: 1,
|
|
138
|
-
alignItems: 'center',
|
|
139
|
-
justifyContent: 'center',
|
|
140
|
-
paddingVertical: 4,
|
|
141
|
-
|
|
142
|
-
// Web specific styles
|
|
143
|
-
_web: {
|
|
144
|
-
display: 'flex',
|
|
145
|
-
flex: undefined,
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
weekdayText: {
|
|
150
|
-
fontSize: 12,
|
|
151
|
-
fontWeight: '500',
|
|
152
|
-
color: theme.colors?.text?.secondary || '#6b7280',
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
calendarGrid: {
|
|
156
|
-
flexDirection: 'row',
|
|
157
|
-
flexWrap: 'wrap',
|
|
158
|
-
marginBottom: 8,
|
|
159
|
-
|
|
160
|
-
// Web specific styles
|
|
161
|
-
_web: {
|
|
162
|
-
display: 'grid',
|
|
163
|
-
gridTemplateColumns: 'repeat(7, 1fr)',
|
|
164
|
-
gap: 2,
|
|
165
|
-
flexDirection: undefined,
|
|
166
|
-
flexWrap: undefined,
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
dayCell: {
|
|
171
|
-
width: '14.28%', // 100% / 7 days
|
|
172
|
-
aspectRatio: 1,
|
|
173
|
-
alignItems: 'center',
|
|
174
|
-
justifyContent: 'center',
|
|
175
|
-
minHeight: 32,
|
|
176
|
-
|
|
177
|
-
// Web specific styles
|
|
178
|
-
_web: {
|
|
179
|
-
display: 'flex',
|
|
180
|
-
width: undefined,
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
dayButton: {
|
|
185
|
-
width: 28,
|
|
186
|
-
height: 28,
|
|
187
|
-
minWidth: 28,
|
|
188
|
-
minHeight: 28,
|
|
189
|
-
padding: 0,
|
|
190
|
-
borderRadius: 6,
|
|
191
|
-
fontSize: 13,
|
|
192
|
-
alignItems: 'center',
|
|
193
|
-
justifyContent: 'center',
|
|
194
|
-
|
|
195
|
-
variants: {
|
|
196
|
-
selected: {
|
|
197
|
-
true: {
|
|
198
|
-
fontWeight: '600',
|
|
199
|
-
},
|
|
200
|
-
false: {
|
|
201
|
-
fontWeight: '400',
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
// Web specific styling
|
|
207
|
-
_web: {
|
|
208
|
-
width: '100%',
|
|
209
|
-
height: '100%',
|
|
210
|
-
maxWidth: 36,
|
|
211
|
-
maxHeight: 36,
|
|
212
|
-
display: 'flex',
|
|
213
|
-
},
|
|
214
|
-
},
|
|
215
|
-
|
|
216
|
-
todaySection: {
|
|
217
|
-
paddingTop: 12,
|
|
218
|
-
borderTopWidth: 1,
|
|
219
|
-
borderTopColor: theme.colors?.border?.secondary || '#f3f4f6',
|
|
220
|
-
|
|
221
|
-
// Web specific border
|
|
222
|
-
_web: {
|
|
223
|
-
borderTop: `1px solid ${theme.colors?.border?.secondary || '#f3f4f6'}`,
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
todayButton: {
|
|
228
|
-
width: '100%',
|
|
229
|
-
},
|
|
230
|
-
}));
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
-
import { View, useMergeRefs } from '@idealyst/components';
|
|
3
|
-
import { CalendarProps } from './types';
|
|
4
|
-
import { CalendarHeader } from '../primitives/CalendarHeader';
|
|
5
|
-
import { CalendarGrid } from '../primitives/CalendarGrid';
|
|
6
|
-
import { CalendarOverlay } from '../primitives/CalendarOverlay';
|
|
7
|
-
import { calendarStyles } from './Calendar.styles';
|
|
8
|
-
import { getWebProps } from 'react-native-unistyles/web';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export const Calendar: React.FC<CalendarProps> = ({
|
|
12
|
-
value,
|
|
13
|
-
onChange,
|
|
14
|
-
minDate,
|
|
15
|
-
maxDate,
|
|
16
|
-
disabled = false,
|
|
17
|
-
currentMonth: controlledCurrentMonth,
|
|
18
|
-
onMonthChange,
|
|
19
|
-
style,
|
|
20
|
-
testID,
|
|
21
|
-
}) => {
|
|
22
|
-
const [internalCurrentMonth, setInternalCurrentMonth] = useState(
|
|
23
|
-
controlledCurrentMonth || value || new Date()
|
|
24
|
-
);
|
|
25
|
-
const [overlayMode, setOverlayMode] = useState<'month' | 'year' | null>(null);
|
|
26
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
27
|
-
|
|
28
|
-
const currentMonth = controlledCurrentMonth || internalCurrentMonth;
|
|
29
|
-
|
|
30
|
-
// Close overlay when clicking outside
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
33
|
-
if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
|
|
34
|
-
setOverlayMode(null);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
if (overlayMode) {
|
|
39
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return () => {
|
|
43
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
44
|
-
};
|
|
45
|
-
}, [overlayMode]);
|
|
46
|
-
|
|
47
|
-
const handleMonthChange = (newMonth: Date) => {
|
|
48
|
-
if (onMonthChange) {
|
|
49
|
-
onMonthChange(newMonth);
|
|
50
|
-
} else {
|
|
51
|
-
setInternalCurrentMonth(newMonth);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const isDateDisabled = (date: Date): boolean => {
|
|
56
|
-
if (disabled) return true;
|
|
57
|
-
if (minDate && date < minDate) return true;
|
|
58
|
-
if (maxDate && date > maxDate) return true;
|
|
59
|
-
return false;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const handleDateSelect = (date: Date) => {
|
|
63
|
-
if (!isDateDisabled(date)) {
|
|
64
|
-
onChange(date);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const goToPreviousMonth = () => {
|
|
69
|
-
const newMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1);
|
|
70
|
-
handleMonthChange(newMonth);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const goToNextMonth = () => {
|
|
74
|
-
const newMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1);
|
|
75
|
-
handleMonthChange(newMonth);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const createDateWithDayAdjustment = (year: number, month: number, day: number): Date => {
|
|
79
|
-
// Get the last day of the target month
|
|
80
|
-
const lastDayOfMonth = new Date(year, month + 1, 0).getDate();
|
|
81
|
-
// Use the smaller of the requested day or the last day of the month
|
|
82
|
-
const adjustedDay = Math.min(day, lastDayOfMonth);
|
|
83
|
-
return new Date(year, month, adjustedDay);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const handleMonthSelect = (monthIndex: number) => {
|
|
87
|
-
const newMonth = new Date(currentMonth.getFullYear(), monthIndex, 1);
|
|
88
|
-
handleMonthChange(newMonth);
|
|
89
|
-
|
|
90
|
-
// Update the selected date if one exists
|
|
91
|
-
if (value) {
|
|
92
|
-
const newDate = createDateWithDayAdjustment(
|
|
93
|
-
currentMonth.getFullYear(),
|
|
94
|
-
monthIndex,
|
|
95
|
-
value.getDate()
|
|
96
|
-
);
|
|
97
|
-
if (!isDateDisabled(newDate)) {
|
|
98
|
-
onChange(newDate);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const handleYearSelect = (year: number) => {
|
|
104
|
-
const newMonth = new Date(year, currentMonth.getMonth(), 1);
|
|
105
|
-
handleMonthChange(newMonth);
|
|
106
|
-
|
|
107
|
-
// Update the selected date if one exists
|
|
108
|
-
if (value) {
|
|
109
|
-
const newDate = createDateWithDayAdjustment(
|
|
110
|
-
year,
|
|
111
|
-
currentMonth.getMonth(),
|
|
112
|
-
value.getDate()
|
|
113
|
-
);
|
|
114
|
-
if (!isDateDisabled(newDate)) {
|
|
115
|
-
onChange(newDate);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const { ref: styleRef, ...containerProps } = getWebProps(calendarStyles.container);
|
|
121
|
-
|
|
122
|
-
const mergedRef = useMergeRefs(containerRef, styleRef);
|
|
123
|
-
|
|
124
|
-
return (
|
|
125
|
-
<div ref={mergedRef as any} {...containerProps} data-testid={testID}>
|
|
126
|
-
<CalendarHeader
|
|
127
|
-
currentMonth={currentMonth}
|
|
128
|
-
onPreviousMonth={goToPreviousMonth}
|
|
129
|
-
onNextMonth={goToNextMonth}
|
|
130
|
-
onMonthClick={() => setOverlayMode('month')}
|
|
131
|
-
onYearClick={() => setOverlayMode('year')}
|
|
132
|
-
disabled={disabled}
|
|
133
|
-
/>
|
|
134
|
-
|
|
135
|
-
<CalendarGrid
|
|
136
|
-
currentMonth={currentMonth}
|
|
137
|
-
selectedDate={value}
|
|
138
|
-
onDateSelect={handleDateSelect}
|
|
139
|
-
onMonthChange={handleMonthChange}
|
|
140
|
-
minDate={minDate}
|
|
141
|
-
maxDate={maxDate}
|
|
142
|
-
disabled={disabled}
|
|
143
|
-
/>
|
|
144
|
-
|
|
145
|
-
{/* Overlay for month/year selection */}
|
|
146
|
-
{overlayMode && (
|
|
147
|
-
<CalendarOverlay
|
|
148
|
-
mode={overlayMode}
|
|
149
|
-
currentMonth={currentMonth.getMonth()}
|
|
150
|
-
currentYear={currentMonth.getFullYear()}
|
|
151
|
-
onMonthSelect={handleMonthSelect}
|
|
152
|
-
onYearSelect={handleYearSelect}
|
|
153
|
-
onClose={() => setOverlayMode(null)}
|
|
154
|
-
disabled={disabled}
|
|
155
|
-
/>
|
|
156
|
-
)}
|
|
157
|
-
</div>
|
|
158
|
-
);
|
|
159
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import React, { useCallback, memo, useRef } from 'react';
|
|
2
|
-
import { View, Text } from '@idealyst/components';
|
|
3
|
-
import { DatePickerProps } from './types';
|
|
4
|
-
import { Calendar } from './Calendar.native';
|
|
5
|
-
import { datePickerStyles } from './DatePicker.styles';
|
|
6
|
-
|
|
7
|
-
const DatePicker: React.FC<DatePickerProps> = memo(({
|
|
8
|
-
value,
|
|
9
|
-
onChange,
|
|
10
|
-
minDate,
|
|
11
|
-
maxDate,
|
|
12
|
-
disabled = false,
|
|
13
|
-
style,
|
|
14
|
-
testID,
|
|
15
|
-
}) => {
|
|
16
|
-
// Store the latest onChange function in a ref to avoid recreating handleDateSelect
|
|
17
|
-
const onChangeRef = useRef(onChange);
|
|
18
|
-
onChangeRef.current = onChange;
|
|
19
|
-
|
|
20
|
-
// Stable callback that uses the latest onChange function
|
|
21
|
-
const handleDateSelect = useCallback((date: Date) => {
|
|
22
|
-
onChangeRef.current(date);
|
|
23
|
-
}, []); // Empty dependency array - this function never changes
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<Calendar
|
|
27
|
-
value={value}
|
|
28
|
-
onChange={handleDateSelect}
|
|
29
|
-
minDate={minDate}
|
|
30
|
-
maxDate={maxDate}
|
|
31
|
-
disabled={disabled}
|
|
32
|
-
style={style}
|
|
33
|
-
testID={testID}
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
}, (prevProps, nextProps) => {
|
|
37
|
-
// Custom comparison to reduce unnecessary re-renders
|
|
38
|
-
// Skip checking onChange since we handle it with a ref
|
|
39
|
-
return (
|
|
40
|
-
prevProps.value?.getTime() === nextProps.value?.getTime() &&
|
|
41
|
-
prevProps.minDate?.getTime() === nextProps.minDate?.getTime() &&
|
|
42
|
-
prevProps.maxDate?.getTime() === nextProps.maxDate?.getTime() &&
|
|
43
|
-
prevProps.disabled === nextProps.disabled &&
|
|
44
|
-
prevProps.style === nextProps.style &&
|
|
45
|
-
prevProps.testID === nextProps.testID
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
DatePicker.displayName = 'DatePicker';
|
|
50
|
-
|
|
51
|
-
export default DatePicker;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
|
|
3
|
-
export const datePickerStyles = StyleSheet.create((theme) => ({
|
|
4
|
-
container: {
|
|
5
|
-
// Base container styles
|
|
6
|
-
},
|
|
7
|
-
|
|
8
|
-
label: {
|
|
9
|
-
marginBottom: theme.spacing?.sm || 8,
|
|
10
|
-
fontSize: theme.typography?.fontSize?.sm || 14,
|
|
11
|
-
fontWeight: '500',
|
|
12
|
-
color: theme.colors?.text?.primary || '#1f2937',
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
picker: {
|
|
16
|
-
borderRadius: theme.borderRadius?.md || 8,
|
|
17
|
-
borderWidth: 1,
|
|
18
|
-
borderColor: theme.colors?.border?.primary || '#e5e7eb',
|
|
19
|
-
backgroundColor: theme.colors?.surface?.primary || '#ffffff',
|
|
20
|
-
padding: theme.spacing?.md || 16,
|
|
21
|
-
shadowColor: '#000',
|
|
22
|
-
shadowOffset: { width: 0, height: 1 },
|
|
23
|
-
shadowOpacity: 0.1,
|
|
24
|
-
shadowRadius: 3,
|
|
25
|
-
elevation: 2,
|
|
26
|
-
|
|
27
|
-
// Web specific styles
|
|
28
|
-
_web: {
|
|
29
|
-
border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
|
|
30
|
-
borderWidth: undefined,
|
|
31
|
-
borderColor: undefined,
|
|
32
|
-
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
|
|
33
|
-
shadowColor: undefined,
|
|
34
|
-
shadowOffset: undefined,
|
|
35
|
-
shadowOpacity: undefined,
|
|
36
|
-
shadowRadius: undefined,
|
|
37
|
-
elevation: undefined,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
selectedDateHeader: {
|
|
42
|
-
marginBottom: theme.spacing?.sm || 12,
|
|
43
|
-
paddingBottom: theme.spacing?.sm || 12,
|
|
44
|
-
borderBottomWidth: 1,
|
|
45
|
-
borderBottomColor: theme.colors?.border?.secondary || '#f3f4f6',
|
|
46
|
-
|
|
47
|
-
// Web specific border
|
|
48
|
-
_web: {
|
|
49
|
-
borderBottom: `1px solid ${theme.colors?.border?.secondary || '#f3f4f6'}`,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
selectedDateLabel: {
|
|
54
|
-
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
55
|
-
color: theme.colors?.text?.secondary || '#6b7280',
|
|
56
|
-
marginBottom: 4,
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
selectedDateValue: {
|
|
60
|
-
fontSize: theme.typography?.fontSize?.md || 16,
|
|
61
|
-
fontWeight: '600',
|
|
62
|
-
color: theme.colors?.text?.primary || '#1f2937',
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
errorText: {
|
|
66
|
-
marginTop: 4,
|
|
67
|
-
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
68
|
-
color: theme.colors?.text?.error || '#dc2626',
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
helperText: {
|
|
72
|
-
marginTop: 4,
|
|
73
|
-
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
74
|
-
color: theme.colors?.text?.secondary || '#6b7280',
|
|
75
|
-
},
|
|
76
|
-
}));
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { DatePickerProps } from './types';
|
|
3
|
-
import { Calendar } from './Calendar.web';
|
|
4
|
-
|
|
5
|
-
const DatePicker: React.FC<DatePickerProps> = ({
|
|
6
|
-
value,
|
|
7
|
-
onChange,
|
|
8
|
-
minDate,
|
|
9
|
-
maxDate,
|
|
10
|
-
disabled = false,
|
|
11
|
-
style,
|
|
12
|
-
testID,
|
|
13
|
-
}) => {
|
|
14
|
-
const handleDateSelect = (date: Date) => {
|
|
15
|
-
onChange(date);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<Calendar
|
|
20
|
-
value={value}
|
|
21
|
-
onChange={handleDateSelect}
|
|
22
|
-
minDate={minDate}
|
|
23
|
-
maxDate={maxDate}
|
|
24
|
-
disabled={disabled}
|
|
25
|
-
style={style}
|
|
26
|
-
testID={testID}
|
|
27
|
-
/>
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export default DatePicker;
|
package/src/DatePicker/index.ts
DELETED
package/src/DatePicker/types.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import { ViewStyle } from 'react-native';
|
|
3
|
-
|
|
4
|
-
export interface DatePickerProps {
|
|
5
|
-
/** Current selected date */
|
|
6
|
-
value?: Date;
|
|
7
|
-
|
|
8
|
-
/** Called when date changes */
|
|
9
|
-
onChange: (date: Date | null) => void;
|
|
10
|
-
|
|
11
|
-
/** Minimum selectable date */
|
|
12
|
-
minDate?: Date;
|
|
13
|
-
|
|
14
|
-
/** Maximum selectable date */
|
|
15
|
-
maxDate?: Date;
|
|
16
|
-
|
|
17
|
-
/** Disabled state */
|
|
18
|
-
disabled?: boolean;
|
|
19
|
-
|
|
20
|
-
/** Placeholder text when no date is selected */
|
|
21
|
-
placeholder?: string;
|
|
22
|
-
|
|
23
|
-
/** Label for the picker */
|
|
24
|
-
label?: string;
|
|
25
|
-
|
|
26
|
-
/** Error message to display */
|
|
27
|
-
error?: string;
|
|
28
|
-
|
|
29
|
-
/** Helper text */
|
|
30
|
-
helperText?: string;
|
|
31
|
-
|
|
32
|
-
/** Date format for display (default: 'MM/dd/yyyy') */
|
|
33
|
-
format?: string;
|
|
34
|
-
|
|
35
|
-
/** Locale for date formatting */
|
|
36
|
-
locale?: string;
|
|
37
|
-
|
|
38
|
-
/** Size variant */
|
|
39
|
-
size?: 'sm' | 'md' | 'lg';
|
|
40
|
-
|
|
41
|
-
/** Visual variant */
|
|
42
|
-
variant?: 'outlined' | 'filled';
|
|
43
|
-
|
|
44
|
-
/** Custom styles */
|
|
45
|
-
style?: ViewStyle;
|
|
46
|
-
|
|
47
|
-
/** Test ID for testing */
|
|
48
|
-
testID?: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface CalendarProps {
|
|
52
|
-
/** Current selected date */
|
|
53
|
-
value?: Date;
|
|
54
|
-
|
|
55
|
-
/** Called when date is selected */
|
|
56
|
-
onChange: (date: Date) => void;
|
|
57
|
-
|
|
58
|
-
/** Minimum selectable date */
|
|
59
|
-
minDate?: Date;
|
|
60
|
-
|
|
61
|
-
/** Maximum selectable date */
|
|
62
|
-
maxDate?: Date;
|
|
63
|
-
|
|
64
|
-
/** Disabled state */
|
|
65
|
-
disabled?: boolean;
|
|
66
|
-
|
|
67
|
-
/** Current month being viewed */
|
|
68
|
-
currentMonth?: Date;
|
|
69
|
-
|
|
70
|
-
/** Called when month changes */
|
|
71
|
-
onMonthChange?: (month: Date) => void;
|
|
72
|
-
|
|
73
|
-
/** Custom styles */
|
|
74
|
-
style?: ViewStyle;
|
|
75
|
-
|
|
76
|
-
/** Test ID for testing */
|
|
77
|
-
testID?: string;
|
|
78
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text } from '@idealyst/components';
|
|
3
|
-
import { DateRangePickerProps, DateRange } from './types';
|
|
4
|
-
import { RangeCalendar } from './RangeCalendar.native';
|
|
5
|
-
import { dateRangePickerStyles } from './DateRangePicker.styles';
|
|
6
|
-
|
|
7
|
-
const DateRangePicker: React.FC<DateRangePickerProps> = ({
|
|
8
|
-
value,
|
|
9
|
-
onChange,
|
|
10
|
-
minDate,
|
|
11
|
-
maxDate,
|
|
12
|
-
disabled = false,
|
|
13
|
-
allowSameDay = true,
|
|
14
|
-
maxDays,
|
|
15
|
-
style,
|
|
16
|
-
testID,
|
|
17
|
-
}) => {
|
|
18
|
-
|
|
19
|
-
const handleRangeChange = (newRange: DateRange) => {
|
|
20
|
-
onChange(newRange.startDate || newRange.endDate ? newRange : null);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<RangeCalendar
|
|
26
|
-
value={value || {}}
|
|
27
|
-
onChange={handleRangeChange}
|
|
28
|
-
minDate={minDate}
|
|
29
|
-
maxDate={maxDate}
|
|
30
|
-
disabled={disabled}
|
|
31
|
-
allowSameDay={allowSameDay}
|
|
32
|
-
maxDays={maxDays}
|
|
33
|
-
style={style}
|
|
34
|
-
testID={testID}
|
|
35
|
-
/>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export default DateRangePicker;
|