@idealyst/datepicker 1.0.0 → 1.0.58

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 (45) hide show
  1. package/package.json +10 -5
  2. package/src/DateInput/DateInput.native.tsx +80 -0
  3. package/src/DateInput/DateInput.styles.tsx +118 -0
  4. package/src/DateInput/DateInput.web.tsx +79 -0
  5. package/src/DateInput/DateInputBase.tsx +233 -0
  6. package/src/DateInput/index.native.ts +2 -0
  7. package/src/DateInput/index.ts +2 -0
  8. package/src/DateInput/types.ts +60 -0
  9. package/src/DatePicker/Calendar.native.tsx +180 -78
  10. package/src/DatePicker/Calendar.styles.tsx +73 -70
  11. package/src/DatePicker/DatePicker.native.tsx +24 -6
  12. package/src/DatePicker/DatePicker.styles.tsx +18 -11
  13. package/src/DatePicker/DatePicker.web.tsx +1 -1
  14. package/src/DatePicker/index.ts +1 -1
  15. package/src/DateRangePicker/RangeCalendar.native.tsx +143 -55
  16. package/src/DateRangePicker/RangeCalendar.styles.tsx +65 -39
  17. package/src/DateRangePicker/RangeCalendar.web.tsx +169 -60
  18. package/src/DateRangePicker/types.ts +9 -0
  19. package/src/DateTimePicker/DateTimePicker.native.tsx +11 -69
  20. package/src/DateTimePicker/DateTimePicker.tsx +12 -70
  21. package/src/DateTimePicker/DateTimePickerBase.tsx +204 -0
  22. package/src/DateTimePicker/TimePicker.native.tsx +9 -196
  23. package/src/DateTimePicker/TimePicker.styles.tsx +4 -2
  24. package/src/DateTimePicker/TimePicker.tsx +9 -401
  25. package/src/DateTimePicker/TimePickerBase.tsx +232 -0
  26. package/src/DateTimePicker/primitives/ClockFace.native.tsx +195 -0
  27. package/src/DateTimePicker/primitives/ClockFace.web.tsx +168 -0
  28. package/src/DateTimePicker/primitives/TimeInput.native.tsx +53 -0
  29. package/src/DateTimePicker/primitives/TimeInput.web.tsx +66 -0
  30. package/src/DateTimePicker/primitives/index.native.ts +2 -0
  31. package/src/DateTimePicker/primitives/index.ts +2 -0
  32. package/src/DateTimePicker/primitives/index.web.ts +2 -0
  33. package/src/DateTimePicker/types.ts +0 -4
  34. package/src/DateTimePicker/utils/dimensions.native.ts +9 -0
  35. package/src/DateTimePicker/utils/dimensions.ts +9 -0
  36. package/src/DateTimePicker/utils/dimensions.web.ts +33 -0
  37. package/src/DateTimeRangePicker/DateTimeRangePicker.native.tsx +10 -199
  38. package/src/DateTimeRangePicker/DateTimeRangePicker.styles.tsx +3 -0
  39. package/src/DateTimeRangePicker/DateTimeRangePicker.web.tsx +11 -131
  40. package/src/DateTimeRangePicker/DateTimeRangePickerBase.tsx +337 -0
  41. package/src/DateTimeRangePicker/types.ts +0 -2
  42. package/src/examples/DatePickerExamples.tsx +42 -118
  43. package/src/index.native.ts +4 -0
  44. package/src/index.ts +4 -0
  45. /package/src/DatePicker/{Calendar.tsx → Calendar.web.tsx} +0 -0
@@ -1,10 +1,73 @@
1
- import React, { useState, useMemo } from 'react';
1
+ import React, { useState, useMemo, useCallback, memo, useRef } from 'react';
2
2
  import { View, Text, Button } from '@idealyst/components';
3
- import { TouchableOpacity } from 'react-native';
3
+ import { TouchableOpacity, StyleSheet } from 'react-native';
4
4
  import { CalendarProps } from './types';
5
5
  import { calendarStyles } from './Calendar.styles';
6
6
 
7
- export const Calendar: React.FC<CalendarProps> = ({
7
+ // Memoized day cell component for better performance
8
+ const DayCell = memo(({
9
+ date,
10
+ isSelected,
11
+ isDisabled,
12
+ onPress,
13
+ dayButtonStyle,
14
+ textColorSelected,
15
+ textColorDefault
16
+ }: {
17
+ date: Date | null;
18
+ isSelected: boolean;
19
+ isDisabled: boolean;
20
+ onPress: (date: Date) => void;
21
+ dayButtonStyle: any;
22
+ textColorSelected: string;
23
+ textColorDefault: string;
24
+ }) => {
25
+ const handlePress = useCallback(() => {
26
+ if (date && !isDisabled) {
27
+ onPress(date);
28
+ }
29
+ }, [date, isDisabled, onPress]);
30
+
31
+ if (!date) {
32
+ return <View style={calendarStyles.dayCell} />;
33
+ }
34
+
35
+ return (
36
+ <View style={calendarStyles.dayCell}>
37
+ <TouchableOpacity
38
+ onPressIn={handlePress}
39
+ disabled={isDisabled}
40
+ style={[
41
+ dayButtonStyle,
42
+ isSelected && styles.selectedButton,
43
+ isDisabled && styles.disabledButton
44
+ ]}
45
+ >
46
+ <Text
47
+ style={[
48
+ styles.dayText,
49
+ { color: isSelected ? textColorSelected : textColorDefault }
50
+ ]}
51
+ >
52
+ {date.getDate()}
53
+ </Text>
54
+ </TouchableOpacity>
55
+ </View>
56
+ );
57
+ }, (prevProps, nextProps) => {
58
+ // Custom comparison function to prevent unnecessary re-renders
59
+ // Only re-render if the relevant props actually changed
60
+ return (
61
+ prevProps.date === nextProps.date &&
62
+ prevProps.isSelected === nextProps.isSelected &&
63
+ prevProps.isDisabled === nextProps.isDisabled &&
64
+ prevProps.onPress === nextProps.onPress
65
+ );
66
+ });
67
+
68
+ DayCell.displayName = 'DayCell';
69
+
70
+ export const Calendar: React.FC<CalendarProps> = memo(({
8
71
  value,
9
72
  onChange,
10
73
  minDate,
@@ -21,74 +84,96 @@ export const Calendar: React.FC<CalendarProps> = ({
21
84
 
22
85
  const currentMonth = controlledCurrentMonth || internalCurrentMonth;
23
86
 
24
- const handleMonthChange = (newMonth: Date) => {
25
- if (onMonthChange) {
26
- onMonthChange(newMonth);
87
+ // Store latest callbacks in refs to avoid recreating functions
88
+ const onChangeRef = useRef(onChange);
89
+ const onMonthChangeRef = useRef(onMonthChange);
90
+ onChangeRef.current = onChange;
91
+ onMonthChangeRef.current = onMonthChange;
92
+
93
+ const handleMonthChange = useCallback((newMonth: Date) => {
94
+ if (onMonthChangeRef.current) {
95
+ onMonthChangeRef.current(newMonth);
27
96
  } else {
28
97
  setInternalCurrentMonth(newMonth);
29
98
  }
30
- };
99
+ }, []);
31
100
 
32
- const { monthStart, monthEnd, daysInMonth, startingDayOfWeek } = useMemo(() => {
101
+ // Memoize calendar data calculation with selection state
102
+ const { calendarDays, monthName } = useMemo(() => {
33
103
  const monthStart = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), 1);
34
104
  const monthEnd = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 0);
35
105
  const daysInMonth = monthEnd.getDate();
36
106
  const startingDayOfWeek = monthStart.getDay();
37
107
 
38
- return { monthStart, monthEnd, daysInMonth, startingDayOfWeek };
39
- }, [currentMonth]);
40
-
41
- const isDateDisabled = (date: Date): boolean => {
42
- if (disabled) return true;
43
- if (minDate && date < minDate) return true;
44
- if (maxDate && date > maxDate) return true;
45
- return false;
46
- };
47
-
48
- const isDateSelected = (date: Date): boolean => {
49
- if (!value) return false;
50
- return (
51
- date.getDate() === value.getDate() &&
52
- date.getMonth() === value.getMonth() &&
53
- date.getFullYear() === value.getFullYear()
54
- );
55
- };
56
-
57
- const handleDateClick = (date: Date) => {
58
- if (!isDateDisabled(date)) {
59
- onChange(date);
108
+ // Pre-calculate all calendar days with their states
109
+ const days: Array<{
110
+ date: Date | null;
111
+ isSelected: boolean;
112
+ isDisabled: boolean;
113
+ key: string;
114
+ }> = [];
115
+
116
+ // Add empty cells for days before month starts
117
+ for (let i = 0; i < startingDayOfWeek; i++) {
118
+ days.push({
119
+ date: null,
120
+ isSelected: false,
121
+ isDisabled: false,
122
+ key: `empty-${i}`
123
+ });
124
+ }
125
+
126
+ // Add days of the month with pre-calculated states
127
+ for (let day = 1; day <= daysInMonth; day++) {
128
+ const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day);
129
+ const dateTime = date.getTime();
130
+
131
+ // Pre-calculate selection state
132
+ const isSelected = value ? (
133
+ date.getDate() === value.getDate() &&
134
+ date.getMonth() === value.getMonth() &&
135
+ date.getFullYear() === value.getFullYear()
136
+ ) : false;
137
+
138
+ // Pre-calculate disabled state
139
+ const isDisabled = disabled ||
140
+ (minDate && dateTime < minDate.getTime()) ||
141
+ (maxDate && dateTime > maxDate.getTime());
142
+
143
+ days.push({
144
+ date,
145
+ isSelected,
146
+ isDisabled: !!isDisabled,
147
+ key: `${date.getFullYear()}-${date.getMonth()}-${day}`
148
+ });
60
149
  }
61
- };
62
150
 
63
- const goToPreviousMonth = () => {
151
+ const name = currentMonth.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
152
+
153
+ return { calendarDays: days, monthName: name };
154
+ }, [currentMonth, value, disabled, minDate, maxDate]);
155
+
156
+
157
+ const handleDateClick = useCallback((date: Date) => {
158
+ onChangeRef.current(date);
159
+ }, []);
160
+
161
+ const goToPreviousMonth = useCallback(() => {
64
162
  const newMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1);
65
163
  handleMonthChange(newMonth);
66
- };
164
+ }, [currentMonth, handleMonthChange]);
67
165
 
68
- const goToNextMonth = () => {
166
+ const goToNextMonth = useCallback(() => {
69
167
  const newMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1);
70
168
  handleMonthChange(newMonth);
71
- };
72
-
73
- const monthName = currentMonth.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
74
-
75
- // Create calendar grid
76
- const calendarDays = [];
77
-
78
- // Add empty cells for days before month starts
79
- for (let i = 0; i < startingDayOfWeek; i++) {
80
- calendarDays.push(null);
81
- }
82
-
83
- // Add days of the month
84
- for (let day = 1; day <= daysInMonth; day++) {
85
- const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day);
86
- calendarDays.push(date);
87
- }
169
+ }, [currentMonth, handleMonthChange]);
88
170
 
89
171
  // Use Unistyles
90
172
  calendarStyles.useVariants({});
91
173
 
174
+ // Pre-calculate styles to avoid inline objects
175
+ const dayButtonStyle = calendarStyles.dayButton;
176
+
92
177
  return (
93
178
  <View style={[calendarStyles.container, style]} testID={testID}>
94
179
  {/* Header */}
@@ -116,7 +201,7 @@ export const Calendar: React.FC<CalendarProps> = ({
116
201
 
117
202
  {/* Weekday headers */}
118
203
  <View style={calendarStyles.weekdayHeader}>
119
- {['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((day) => (
204
+ {weekdays.map((day) => (
120
205
  <View key={day} style={calendarStyles.weekdayCell}>
121
206
  <Text style={calendarStyles.weekdayText}>
122
207
  {day}
@@ -127,33 +212,50 @@ export const Calendar: React.FC<CalendarProps> = ({
127
212
 
128
213
  {/* Calendar grid */}
129
214
  <View style={calendarStyles.calendarGrid}>
130
- {calendarDays.map((date, index) => (
131
- <View key={index} style={calendarStyles.dayCell}>
132
- {date && (
133
- <TouchableOpacity
134
- onPress={() => handleDateClick(date)}
135
- disabled={isDateDisabled(date)}
136
- style={[
137
- calendarStyles.dayButton,
138
- {
139
- backgroundColor: isDateSelected(date) ? '#3b82f6' : 'transparent',
140
- opacity: isDateDisabled(date) ? 0.5 : 1,
141
- }
142
- ]}
143
- >
144
- <Text
145
- style={{
146
- color: isDateSelected(date) ? 'white' : 'black',
147
- fontSize: 13,
148
- }}
149
- >
150
- {date.getDate()}
151
- </Text>
152
- </TouchableOpacity>
153
- )}
154
- </View>
215
+ {calendarDays.map((dayInfo) => (
216
+ <DayCell
217
+ key={dayInfo.key}
218
+ date={dayInfo.date}
219
+ isSelected={dayInfo.isSelected}
220
+ isDisabled={dayInfo.isDisabled}
221
+ onPress={handleDateClick}
222
+ dayButtonStyle={dayButtonStyle}
223
+ textColorSelected="#ffffff"
224
+ textColorDefault="#000000"
225
+ />
155
226
  ))}
156
227
  </View>
157
228
  </View>
158
229
  );
159
- };
230
+ }, (prevProps, nextProps) => {
231
+ // Custom comparison to prevent unnecessary re-renders
232
+ // Skip checking callbacks since we handle them with refs
233
+ return (
234
+ prevProps.value?.getTime() === nextProps.value?.getTime() &&
235
+ prevProps.minDate?.getTime() === nextProps.minDate?.getTime() &&
236
+ prevProps.maxDate?.getTime() === nextProps.maxDate?.getTime() &&
237
+ prevProps.disabled === nextProps.disabled &&
238
+ prevProps.currentMonth?.getTime() === nextProps.currentMonth?.getTime() &&
239
+ prevProps.style === nextProps.style &&
240
+ prevProps.testID === nextProps.testID
241
+ );
242
+ });
243
+
244
+ Calendar.displayName = 'Calendar';
245
+
246
+ // Static weekday labels
247
+ const weekdays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
248
+
249
+ // Pre-defined styles to avoid inline style objects
250
+ const styles = StyleSheet.create({
251
+ selectedButton: {
252
+ backgroundColor: '#3b82f6'
253
+ },
254
+ disabledButton: {
255
+ opacity: 0.5
256
+ },
257
+ dayText: {
258
+ fontSize: 13,
259
+ textAlign: 'center'
260
+ }
261
+ });
@@ -38,47 +38,42 @@ export const calendarStyles = StyleSheet.create((theme) => ({
38
38
  padding: theme.spacing?.sm || 12,
39
39
  backgroundColor: theme.colors?.surface?.secondary || '#f9fafb',
40
40
  borderRadius: theme.borderRadius?.md || 8,
41
- border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
41
+ borderWidth: 1,
42
+ borderColor: theme.colors?.border?.primary || '#e5e7eb',
42
43
 
43
- // Native specific styles
44
- _native: {
45
- borderWidth: 1,
46
- borderColor: theme.colors?.border?.primary || '#e5e7eb',
44
+ // Web specific styles
45
+ _web: {
46
+ border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
47
+ borderWidth: undefined,
48
+ borderColor: undefined,
47
49
  },
48
50
  },
49
51
 
50
52
  monthPickerGrid: {
51
- display: 'flex',
52
53
  flexDirection: 'row',
53
54
  flexWrap: 'wrap',
54
- gap: 6,
55
- width: '100%',
56
55
  justifyContent: 'space-between',
56
+ width: '100%',
57
57
 
58
- // Native fallback
59
- _native: {
60
- flexDirection: 'row',
61
- flexWrap: 'wrap',
62
- justifyContent: 'space-between',
58
+ // Web specific styles
59
+ _web: {
60
+ display: 'flex',
61
+ gap: 6,
63
62
  },
64
63
  },
65
64
 
66
65
  yearPickerGrid: {
67
- display: 'flex',
68
66
  flexDirection: 'row',
69
67
  flexWrap: 'wrap',
70
- gap: 4,
68
+ justifyContent: 'space-between',
71
69
  maxHeight: 200,
72
- overflowY: 'auto',
73
70
  width: '100%',
74
- justifyContent: 'space-between',
75
71
 
76
- // Native fallback
77
- _native: {
78
- flexDirection: 'row',
79
- flexWrap: 'wrap',
80
- justifyContent: 'space-between',
81
- maxHeight: 200,
72
+ // Web specific styles
73
+ _web: {
74
+ display: 'flex',
75
+ gap: 4,
76
+ overflowY: 'auto',
82
77
  },
83
78
  },
84
79
 
@@ -87,56 +82,64 @@ export const calendarStyles = StyleSheet.create((theme) => ({
87
82
  paddingHorizontal: theme.spacing?.xs || 6,
88
83
  paddingVertical: theme.spacing?.xs || 4,
89
84
  minHeight: 32,
90
- display: 'flex',
91
85
  justifyContent: 'center',
92
86
  alignItems: 'center',
87
+ width: '30%',
88
+ marginBottom: 4,
93
89
 
94
90
  // Month buttons: 3 per row with equal spacing
95
91
  variants: {
96
92
  monthButton: {
97
93
  true: {
98
- flex: '1 0 30%',
99
- maxWidth: 'calc(33.333% - 4px)',
94
+ _web: {
95
+ flex: '1 0 30%',
96
+ maxWidth: 'calc(33.333% - 4px)',
97
+ width: undefined,
98
+ },
100
99
  },
101
100
  },
102
101
  yearButton: {
103
102
  true: {
104
- flex: '1 0 22%',
105
- maxWidth: 'calc(25% - 3px)',
103
+ _web: {
104
+ flex: '1 0 22%',
105
+ maxWidth: 'calc(25% - 3px)',
106
+ width: undefined,
107
+ },
106
108
  },
107
109
  },
108
110
  },
109
111
 
110
- // Native specific sizing
111
- _native: {
112
- width: '30%',
113
- marginBottom: 4,
112
+ // Web specific styles
113
+ _web: {
114
+ display: 'flex',
115
+ width: undefined,
116
+ marginBottom: undefined,
114
117
  },
115
118
  },
116
119
 
117
120
  weekdayHeader: {
118
- display: 'grid',
119
- gridTemplateColumns: 'repeat(7, 1fr)',
120
- gap: 2,
121
+ flexDirection: 'row',
121
122
  marginBottom: theme.spacing?.xs || 8,
122
123
 
123
- // Native fallback
124
- _native: {
125
- flexDirection: 'row',
124
+ // Web specific styles
125
+ _web: {
126
+ display: 'grid',
127
+ gridTemplateColumns: 'repeat(7, 1fr)',
128
+ gap: 2,
129
+ flexDirection: undefined,
126
130
  },
127
131
  },
128
132
 
129
133
  weekdayCell: {
130
- display: 'flex',
134
+ flex: 1,
131
135
  alignItems: 'center',
132
136
  justifyContent: 'center',
133
137
  paddingVertical: theme.spacing?.xs || 4,
134
138
 
135
- // Native fallback
136
- _native: {
137
- flex: 1,
138
- alignItems: 'center',
139
- paddingVertical: theme.spacing?.xs || 4,
139
+ // Web specific styles
140
+ _web: {
141
+ display: 'flex',
142
+ flex: undefined,
140
143
  },
141
144
  },
142
145
 
@@ -147,44 +150,44 @@ export const calendarStyles = StyleSheet.create((theme) => ({
147
150
  },
148
151
 
149
152
  calendarGrid: {
150
- display: 'grid',
151
- gridTemplateColumns: 'repeat(7, 1fr)',
152
- gap: 2,
153
+ flexDirection: 'row',
154
+ flexWrap: 'wrap',
153
155
  marginBottom: theme.spacing?.xs || 8,
154
156
 
155
- // Native fallback
156
- _native: {
157
- flexDirection: 'row',
158
- flexWrap: 'wrap',
157
+ // Web specific styles
158
+ _web: {
159
+ display: 'grid',
160
+ gridTemplateColumns: 'repeat(7, 1fr)',
161
+ gap: 2,
162
+ flexDirection: undefined,
163
+ flexWrap: undefined,
159
164
  },
160
165
  },
161
166
 
162
167
  dayCell: {
163
- display: 'flex',
168
+ width: '14.28%', // 100% / 7 days
169
+ aspectRatio: 1,
164
170
  alignItems: 'center',
165
171
  justifyContent: 'center',
166
- aspectRatio: '1',
167
172
  minHeight: 32,
168
173
 
169
- // Native specific sizing
170
- _native: {
171
- width: '14.28%', // 100% / 7 days
172
- aspectRatio: 1,
173
- alignItems: 'center',
174
- justifyContent: 'center',
174
+ // Web specific styles
175
+ _web: {
176
+ display: 'flex',
177
+ width: undefined,
175
178
  },
176
179
  },
177
180
 
178
181
  dayButton: {
179
- width: '100%',
180
- height: '100%',
181
- maxWidth: 36,
182
- maxHeight: 36,
182
+ width: 28,
183
+ height: 28,
183
184
  minWidth: 28,
184
185
  minHeight: 28,
185
186
  padding: 0,
186
187
  borderRadius: theme.borderRadius?.sm || 6,
187
188
  fontSize: theme.typography?.sizes?.small || 13,
189
+ alignItems: 'center',
190
+ justifyContent: 'center',
188
191
 
189
192
  variants: {
190
193
  selected: {
@@ -197,13 +200,13 @@ export const calendarStyles = StyleSheet.create((theme) => ({
197
200
  },
198
201
  },
199
202
 
200
- // Native specific styling
201
- _native: {
202
- width: 28,
203
- height: 28,
204
- minWidth: 28,
205
- minHeight: 28,
206
- borderRadius: theme.borderRadius?.sm || 6,
203
+ // Web specific styling
204
+ _web: {
205
+ width: '100%',
206
+ height: '100%',
207
+ maxWidth: 36,
208
+ maxHeight: 36,
209
+ display: 'flex',
207
210
  },
208
211
  },
209
212
 
@@ -1,10 +1,10 @@
1
- import React, { useState } from 'react';
1
+ import React, { useCallback, memo, useRef } from 'react';
2
2
  import { View, Text } from '@idealyst/components';
3
3
  import { DatePickerProps } from './types';
4
4
  import { Calendar } from './Calendar.native';
5
5
  import { datePickerStyles } from './DatePicker.styles';
6
6
 
7
- const DatePicker: React.FC<DatePickerProps> = ({
7
+ const DatePicker: React.FC<DatePickerProps> = memo(({
8
8
  value,
9
9
  onChange,
10
10
  minDate,
@@ -13,9 +13,14 @@ const DatePicker: React.FC<DatePickerProps> = ({
13
13
  style,
14
14
  testID,
15
15
  }) => {
16
- const handleDateSelect = (date: Date) => {
17
- onChange(date);
18
- };
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
19
24
 
20
25
  return (
21
26
  <Calendar
@@ -28,6 +33,19 @@ const DatePicker: React.FC<DatePickerProps> = ({
28
33
  testID={testID}
29
34
  />
30
35
  );
31
- };
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';
32
50
 
33
51
  export default DatePicker;
@@ -14,20 +14,27 @@ export const datePickerStyles = StyleSheet.create((theme) => ({
14
14
 
15
15
  picker: {
16
16
  borderRadius: theme.borderRadius?.md || 8,
17
- border: `1px solid ${theme.colors?.border?.primary || '#e5e7eb'}`,
17
+ borderWidth: 1,
18
+ borderColor: theme.colors?.border?.primary || '#e5e7eb',
18
19
  backgroundColor: theme.colors?.surface?.primary || '#ffffff',
19
20
  padding: theme.spacing?.md || 16,
20
- boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
21
+ shadowColor: '#000',
22
+ shadowOffset: { width: 0, height: 1 },
23
+ shadowOpacity: 0.1,
24
+ shadowRadius: 3,
25
+ elevation: 2,
21
26
 
22
- // Native specific styles
23
- _native: {
24
- borderWidth: 1,
25
- borderColor: theme.colors?.border?.primary || '#e5e7eb',
26
- shadowColor: '#000',
27
- shadowOffset: { width: 0, height: 1 },
28
- shadowOpacity: 0.1,
29
- shadowRadius: 3,
30
- elevation: 2,
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,
31
38
  },
32
39
  },
33
40
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { DatePickerProps } from './types';
3
- import { Calendar } from './Calendar';
3
+ import { Calendar } from './Calendar.web';
4
4
 
5
5
  const DatePicker: React.FC<DatePickerProps> = ({
6
6
  value,
@@ -1,3 +1,3 @@
1
1
  export { default as DatePicker } from './DatePicker.web';
2
- export { Calendar } from './Calendar';
2
+ export { Calendar } from './Calendar.web';
3
3
  export type { DatePickerProps, CalendarProps } from './types';