@idealyst/datepicker 1.0.83 → 1.0.85
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 +1 -1
- package/package.json +8 -3
- package/src/DateInput/DateInput.native.tsx +1 -1
- package/src/DateInput/DateInput.styles.tsx +3 -3
- package/src/DateInput/DateInput.web.tsx +1 -1
- package/src/DateInput/types.ts +1 -1
- package/src/DatePicker/Calendar.native.tsx +2 -2
- package/src/DatePicker/Calendar.styles.tsx +24 -21
- package/src/DatePicker/Calendar.web.tsx +9 -4
- package/src/DatePicker/DatePicker.styles.tsx +5 -5
- package/src/DatePicker/types.ts +1 -1
- package/src/DateRangePicker/DateRangePicker.styles.tsx +7 -7
- package/src/DateRangePicker/RangeCalendar.native.tsx +15 -15
- package/src/DateRangePicker/RangeCalendar.styles.tsx +6 -2
- package/src/DateRangePicker/RangeCalendar.web.tsx +16 -16
- package/src/DateRangePicker/types.ts +1 -1
- package/src/DateTimePicker/DateTimePicker.styles.tsx +33 -6
- package/src/DateTimePicker/DateTimePickerBase.tsx +10 -29
- package/src/DateTimePicker/TimePicker.styles.tsx +2 -5
- package/src/DateTimePicker/TimePickerBase.tsx +1 -1
- package/src/DateTimePicker/types.ts +1 -1
- package/src/DateTimeRangePicker/DateTimeRangePicker.styles.tsx +27 -7
- package/src/DateTimeRangePicker/DateTimeRangePickerBase.tsx +11 -21
- package/src/DateTimeRangePicker/types.ts +1 -1
- package/src/examples/DatePickerExamples.tsx +29 -29
- package/src/primitives/CalendarGrid/CalendarGrid.styles.tsx +13 -24
- package/src/primitives/CalendarGrid/CalendarGrid.tsx +19 -11
- package/src/primitives/CalendarHeader/CalendarHeader.tsx +15 -15
- package/src/primitives/CalendarOverlay/CalendarOverlay.styles.tsx +7 -2
- package/src/primitives/CalendarOverlay/CalendarOverlay.tsx +38 -32
|
@@ -95,17 +95,7 @@ export const DateTimePickerBase: React.FC<DateTimePickerBaseProps> = ({
|
|
|
95
95
|
return (
|
|
96
96
|
<View style={[dateTimePickerStyles.container, style]} testID={testID} data-testid={testID}>
|
|
97
97
|
{/* Side by side layout */}
|
|
98
|
-
<View style={
|
|
99
|
-
flexDirection: 'row',
|
|
100
|
-
gap: 16,
|
|
101
|
-
alignItems: 'flex-start',
|
|
102
|
-
_web: {
|
|
103
|
-
display: 'flex',
|
|
104
|
-
flexDirection: 'row',
|
|
105
|
-
gap: 16,
|
|
106
|
-
alignItems: 'flex-start',
|
|
107
|
-
}
|
|
108
|
-
}}>
|
|
98
|
+
<View style={dateTimePickerStyles.sideBySideLayout}>
|
|
109
99
|
{renderCalendar({
|
|
110
100
|
value,
|
|
111
101
|
onChange: handleDateChange,
|
|
@@ -113,7 +103,7 @@ export const DateTimePickerBase: React.FC<DateTimePickerBaseProps> = ({
|
|
|
113
103
|
maxDate,
|
|
114
104
|
disabled,
|
|
115
105
|
})}
|
|
116
|
-
|
|
106
|
+
|
|
117
107
|
{renderTimePicker({
|
|
118
108
|
value: value || new Date(),
|
|
119
109
|
onChange: handleTimeChange,
|
|
@@ -133,31 +123,22 @@ export const DateTimePickerBase: React.FC<DateTimePickerBaseProps> = ({
|
|
|
133
123
|
return (
|
|
134
124
|
<View style={[dateTimePickerStyles.container, style]} testID={testID} data-testid={testID}>
|
|
135
125
|
{/* Step Navigation */}
|
|
136
|
-
<View style={
|
|
137
|
-
flexDirection: 'row',
|
|
138
|
-
gap: 8,
|
|
139
|
-
marginBottom: 8,
|
|
140
|
-
_web: {
|
|
141
|
-
display: 'flex',
|
|
142
|
-
flexDirection: 'row',
|
|
143
|
-
gap: 8,
|
|
144
|
-
}
|
|
145
|
-
}}>
|
|
126
|
+
<View style={dateTimePickerStyles.stepNavigation}>
|
|
146
127
|
<Button
|
|
147
128
|
variant={isDateStep ? 'primary' : 'outlined'}
|
|
148
|
-
size="
|
|
129
|
+
size="sm"
|
|
149
130
|
onPress={() => setViewMode('date')}
|
|
150
131
|
disabled={disabled}
|
|
151
|
-
style={
|
|
132
|
+
style={dateTimePickerStyles.stepButton}
|
|
152
133
|
>
|
|
153
134
|
1. Date
|
|
154
135
|
</Button>
|
|
155
136
|
<Button
|
|
156
137
|
variant={isTimeStep ? 'primary' : 'outlined'}
|
|
157
|
-
size="
|
|
138
|
+
size="sm"
|
|
158
139
|
onPress={() => setViewMode('time')}
|
|
159
140
|
disabled={disabled || !value}
|
|
160
|
-
style={
|
|
141
|
+
style={dateTimePickerStyles.stepButton}
|
|
161
142
|
>
|
|
162
143
|
2. Time
|
|
163
144
|
</Button>
|
|
@@ -185,12 +166,12 @@ export const DateTimePickerBase: React.FC<DateTimePickerBaseProps> = ({
|
|
|
185
166
|
mode: timeMode,
|
|
186
167
|
step: timeStep,
|
|
187
168
|
})}
|
|
188
|
-
|
|
169
|
+
|
|
189
170
|
{/* Back to Date button */}
|
|
190
|
-
<View style={
|
|
171
|
+
<View style={dateTimePickerStyles.backButtonContainer}>
|
|
191
172
|
<Button
|
|
192
173
|
variant="text"
|
|
193
|
-
size="
|
|
174
|
+
size="sm"
|
|
194
175
|
onPress={() => setViewMode('date')}
|
|
195
176
|
disabled={disabled}
|
|
196
177
|
>
|
|
@@ -19,8 +19,6 @@ export const timePickerStyles = StyleSheet.create((theme) => ({
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
clockSvg: {
|
|
22
|
-
cursor: 'pointer',
|
|
23
|
-
|
|
24
22
|
_web: {
|
|
25
23
|
cursor: 'pointer',
|
|
26
24
|
}
|
|
@@ -48,7 +46,7 @@ export const timePickerStyles = StyleSheet.create((theme) => ({
|
|
|
48
46
|
backgroundColor: 'transparent',
|
|
49
47
|
paddingHorizontal: 0,
|
|
50
48
|
paddingVertical: 0,
|
|
51
|
-
|
|
49
|
+
|
|
52
50
|
_web: {
|
|
53
51
|
border: 'none',
|
|
54
52
|
borderBottom: 'none',
|
|
@@ -95,8 +93,7 @@ export const timePickerStyles = StyleSheet.create((theme) => ({
|
|
|
95
93
|
fontWeight: '500',
|
|
96
94
|
borderRadius: 4,
|
|
97
95
|
borderWidth: 0,
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
|
|
100
97
|
_web: {
|
|
101
98
|
border: 'none',
|
|
102
99
|
cursor: 'pointer',
|
|
@@ -6,7 +6,7 @@ export const dateTimeRangePickerStyles = StyleSheet.create((theme) => ({
|
|
|
6
6
|
},
|
|
7
7
|
|
|
8
8
|
label: {
|
|
9
|
-
fontSize: theme.typography?.
|
|
9
|
+
fontSize: theme.typography?.fontSize?.sm || 14,
|
|
10
10
|
fontWeight: '600',
|
|
11
11
|
color: theme.colors?.text?.primary || '#111827',
|
|
12
12
|
marginBottom: theme.spacing?.xs || 4,
|
|
@@ -33,13 +33,13 @@ export const dateTimeRangePickerStyles = StyleSheet.create((theme) => ({
|
|
|
33
33
|
},
|
|
34
34
|
|
|
35
35
|
selectedRangeLabel: {
|
|
36
|
-
fontSize: theme.typography?.
|
|
36
|
+
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
37
37
|
fontWeight: '500',
|
|
38
38
|
color: theme.colors?.text?.secondary || '#6b7280',
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
selectedRangeValue: {
|
|
42
|
-
fontSize: theme.typography?.
|
|
42
|
+
fontSize: theme.typography?.fontSize?.md || 16,
|
|
43
43
|
fontWeight: '600',
|
|
44
44
|
color: theme.colors?.text?.primary || '#111827',
|
|
45
45
|
},
|
|
@@ -49,7 +49,7 @@ export const dateTimeRangePickerStyles = StyleSheet.create((theme) => ({
|
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
sectionLabel: {
|
|
52
|
-
fontSize: theme.typography?.
|
|
52
|
+
fontSize: theme.typography?.fontSize?.sm || 14,
|
|
53
53
|
fontWeight: '600',
|
|
54
54
|
color: theme.colors?.text?.primary || '#111827',
|
|
55
55
|
},
|
|
@@ -79,20 +79,40 @@ export const dateTimeRangePickerStyles = StyleSheet.create((theme) => ({
|
|
|
79
79
|
},
|
|
80
80
|
|
|
81
81
|
timeGroupLabel: {
|
|
82
|
-
fontSize: theme.typography?.
|
|
82
|
+
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
83
83
|
fontWeight: '500',
|
|
84
84
|
color: theme.colors?.text?.secondary || '#6b7280',
|
|
85
85
|
},
|
|
86
86
|
|
|
87
87
|
errorText: {
|
|
88
|
-
fontSize: theme.typography?.
|
|
88
|
+
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
89
89
|
color: theme.colors?.semantic?.error || '#dc2626',
|
|
90
90
|
marginTop: theme.spacing?.xs || 4,
|
|
91
91
|
},
|
|
92
92
|
|
|
93
93
|
helperText: {
|
|
94
|
-
fontSize: theme.typography?.
|
|
94
|
+
fontSize: theme.typography?.fontSize?.sm || 12,
|
|
95
95
|
color: theme.colors?.text?.secondary || '#6b7280',
|
|
96
96
|
marginTop: theme.spacing?.xs || 4,
|
|
97
97
|
},
|
|
98
|
+
|
|
99
|
+
sideBySideLayout: {
|
|
100
|
+
flexDirection: 'row',
|
|
101
|
+
gap: theme.spacing?.lg || 24,
|
|
102
|
+
alignItems: 'flex-start',
|
|
103
|
+
_web: {
|
|
104
|
+
display: 'flex',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
timeSelectionPanel: {
|
|
109
|
+
minWidth: 220,
|
|
110
|
+
flexShrink: 0,
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
navigationContainer: {
|
|
114
|
+
marginTop: theme.spacing?.sm || 12,
|
|
115
|
+
flexDirection: 'row',
|
|
116
|
+
justifyContent: 'space-between',
|
|
117
|
+
},
|
|
98
118
|
}));
|
|
@@ -130,17 +130,7 @@ export const DateTimeRangePickerBase: React.FC<DateTimeRangePickerBaseProps> = (
|
|
|
130
130
|
return (
|
|
131
131
|
<View style={[dateTimeRangePickerStyles.container, style]} testID={testID} data-testid={testID}>
|
|
132
132
|
{/* Side by side layout */}
|
|
133
|
-
<View style={
|
|
134
|
-
flexDirection: 'row',
|
|
135
|
-
gap: 24,
|
|
136
|
-
alignItems: 'flex-start',
|
|
137
|
-
_web: {
|
|
138
|
-
display: 'flex',
|
|
139
|
-
flexDirection: 'row',
|
|
140
|
-
gap: 24,
|
|
141
|
-
alignItems: 'flex-start',
|
|
142
|
-
}
|
|
143
|
-
}}>
|
|
133
|
+
<View style={dateTimeRangePickerStyles.sideBySideLayout}>
|
|
144
134
|
{renderRangeCalendar({
|
|
145
135
|
value: value || {},
|
|
146
136
|
onChange: handleDateRangeChange,
|
|
@@ -153,10 +143,10 @@ export const DateTimeRangePickerBase: React.FC<DateTimeRangePickerBaseProps> = (
|
|
|
153
143
|
showTimes: true,
|
|
154
144
|
timeMode,
|
|
155
145
|
})}
|
|
156
|
-
|
|
146
|
+
|
|
157
147
|
{/* Time Selection Panel */}
|
|
158
148
|
{(value?.startDate || value?.endDate) && (
|
|
159
|
-
<View style={
|
|
149
|
+
<View style={dateTimeRangePickerStyles.timeSelectionPanel}>
|
|
160
150
|
{/* Time Selection Tabs */}
|
|
161
151
|
<View style={timePickerStyles.tabBar}>
|
|
162
152
|
<Button
|
|
@@ -276,12 +266,12 @@ export const DateTimeRangePickerBase: React.FC<DateTimeRangePickerBaseProps> = (
|
|
|
276
266
|
mode: timeMode,
|
|
277
267
|
step: timeStep,
|
|
278
268
|
})}
|
|
279
|
-
|
|
269
|
+
|
|
280
270
|
{/* Navigation */}
|
|
281
|
-
<View style={
|
|
271
|
+
<View style={dateTimeRangePickerStyles.navigationContainer}>
|
|
282
272
|
<Button
|
|
283
273
|
variant="text"
|
|
284
|
-
size="
|
|
274
|
+
size="sm"
|
|
285
275
|
onPress={() => setViewMode('date')}
|
|
286
276
|
disabled={disabled}
|
|
287
277
|
>
|
|
@@ -290,7 +280,7 @@ export const DateTimeRangePickerBase: React.FC<DateTimeRangePickerBaseProps> = (
|
|
|
290
280
|
{value.endDate && (
|
|
291
281
|
<Button
|
|
292
282
|
variant="text"
|
|
293
|
-
size="
|
|
283
|
+
size="sm"
|
|
294
284
|
onPress={() => setViewMode('end-time')}
|
|
295
285
|
disabled={disabled}
|
|
296
286
|
>
|
|
@@ -310,12 +300,12 @@ export const DateTimeRangePickerBase: React.FC<DateTimeRangePickerBaseProps> = (
|
|
|
310
300
|
mode: timeMode,
|
|
311
301
|
step: timeStep,
|
|
312
302
|
})}
|
|
313
|
-
|
|
303
|
+
|
|
314
304
|
{/* Navigation */}
|
|
315
|
-
<View style={
|
|
305
|
+
<View style={dateTimeRangePickerStyles.navigationContainer}>
|
|
316
306
|
<Button
|
|
317
307
|
variant="text"
|
|
318
|
-
size="
|
|
308
|
+
size="sm"
|
|
319
309
|
onPress={() => setViewMode('start-time')}
|
|
320
310
|
disabled={disabled}
|
|
321
311
|
>
|
|
@@ -323,7 +313,7 @@ export const DateTimeRangePickerBase: React.FC<DateTimeRangePickerBaseProps> = (
|
|
|
323
313
|
</Button>
|
|
324
314
|
<Button
|
|
325
315
|
variant="text"
|
|
326
|
-
size="
|
|
316
|
+
size="sm"
|
|
327
317
|
onPress={() => setViewMode('date')}
|
|
328
318
|
disabled={disabled}
|
|
329
319
|
>
|
|
@@ -21,17 +21,17 @@ export const DatePickerExamples = () => {
|
|
|
21
21
|
return (
|
|
22
22
|
<Screen background="primary" padding="lg">
|
|
23
23
|
<View spacing="none">
|
|
24
|
-
<Text size="
|
|
24
|
+
<Text size="lg" weight="bold" align="center">
|
|
25
25
|
DatePicker & DateTimePicker Examples
|
|
26
26
|
</Text>
|
|
27
27
|
|
|
28
28
|
{/* DateTime Picker Examples */}
|
|
29
29
|
<View spacing="md">
|
|
30
|
-
<Text size="
|
|
30
|
+
<Text size="md" weight="semibold">DateTimePicker Examples</Text>
|
|
31
31
|
|
|
32
32
|
{/* Basic DateTime */}
|
|
33
33
|
<View spacing="sm">
|
|
34
|
-
<Text size="
|
|
34
|
+
<Text size="sm" weight="medium">Basic DateTimePicker (12-hour)</Text>
|
|
35
35
|
<DateTimePicker
|
|
36
36
|
value={dateTime}
|
|
37
37
|
onChange={setDateTime}
|
|
@@ -40,7 +40,7 @@ export const DatePickerExamples = () => {
|
|
|
40
40
|
helperText="Responsive layout - side-by-side on large screens, step-by-step on mobile"
|
|
41
41
|
/>
|
|
42
42
|
{dateTime && (
|
|
43
|
-
<Text size="
|
|
43
|
+
<Text size="sm" color="secondary">
|
|
44
44
|
Selected: {dateTime.toLocaleString()}
|
|
45
45
|
</Text>
|
|
46
46
|
)}
|
|
@@ -48,7 +48,7 @@ export const DatePickerExamples = () => {
|
|
|
48
48
|
|
|
49
49
|
{/* 24-hour format */}
|
|
50
50
|
<View spacing="sm">
|
|
51
|
-
<Text size="
|
|
51
|
+
<Text size="sm" weight="medium">24-hour format with seconds</Text>
|
|
52
52
|
<DateTimePicker
|
|
53
53
|
value={dateTime24h}
|
|
54
54
|
onChange={setDateTime24h}
|
|
@@ -59,7 +59,7 @@ export const DatePickerExamples = () => {
|
|
|
59
59
|
helperText="24-hour format with seconds, 5-minute steps"
|
|
60
60
|
/>
|
|
61
61
|
{dateTime24h && (
|
|
62
|
-
<Text size="
|
|
62
|
+
<Text size="sm" color="secondary">
|
|
63
63
|
Selected: {dateTime24h.toLocaleString()}
|
|
64
64
|
</Text>
|
|
65
65
|
)}
|
|
@@ -68,7 +68,7 @@ export const DatePickerExamples = () => {
|
|
|
68
68
|
|
|
69
69
|
{/* Basic DatePicker */}
|
|
70
70
|
<View spacing="md">
|
|
71
|
-
<Text size="
|
|
71
|
+
<Text size="md" weight="semibold">Basic DatePicker</Text>
|
|
72
72
|
<DatePicker
|
|
73
73
|
value={basicDate}
|
|
74
74
|
onChange={setBasicDate}
|
|
@@ -77,7 +77,7 @@ export const DatePickerExamples = () => {
|
|
|
77
77
|
helperText="Pick any date"
|
|
78
78
|
/>
|
|
79
79
|
{basicDate && (
|
|
80
|
-
<Text size="
|
|
80
|
+
<Text size="sm" color="secondary">
|
|
81
81
|
Selected: {basicDate.toDateString()}
|
|
82
82
|
</Text>
|
|
83
83
|
)}
|
|
@@ -85,7 +85,7 @@ export const DatePickerExamples = () => {
|
|
|
85
85
|
|
|
86
86
|
{/* Date Range Restricted */}
|
|
87
87
|
<View spacing="md">
|
|
88
|
-
<Text size="
|
|
88
|
+
<Text size="md" weight="semibold">Date Range Restricted</Text>
|
|
89
89
|
<DatePicker
|
|
90
90
|
value={rangeDate}
|
|
91
91
|
onChange={setRangeDate}
|
|
@@ -96,7 +96,7 @@ export const DatePickerExamples = () => {
|
|
|
96
96
|
helperText="Only dates between tomorrow and next month"
|
|
97
97
|
/>
|
|
98
98
|
{rangeDate && (
|
|
99
|
-
<Text size="
|
|
99
|
+
<Text size="sm" color="secondary">
|
|
100
100
|
Selected: {rangeDate.toDateString()}
|
|
101
101
|
</Text>
|
|
102
102
|
)}
|
|
@@ -104,7 +104,7 @@ export const DatePickerExamples = () => {
|
|
|
104
104
|
|
|
105
105
|
{/* Disabled DatePicker */}
|
|
106
106
|
<View spacing="md">
|
|
107
|
-
<Text size="
|
|
107
|
+
<Text size="md" weight="semibold">Disabled DatePicker</Text>
|
|
108
108
|
<DatePicker
|
|
109
109
|
value={disabledDate}
|
|
110
110
|
onChange={setDisabledDate}
|
|
@@ -118,16 +118,16 @@ export const DatePickerExamples = () => {
|
|
|
118
118
|
|
|
119
119
|
{/* Actions */}
|
|
120
120
|
<View spacing="md">
|
|
121
|
-
<Text size="
|
|
122
|
-
<View
|
|
123
|
-
<Button
|
|
124
|
-
|
|
121
|
+
<Text size="md" weight="semibold">Actions</Text>
|
|
122
|
+
<View>
|
|
123
|
+
<Button
|
|
124
|
+
type='outlined'
|
|
125
125
|
onPress={() => setBasicDate(new Date())}
|
|
126
126
|
>
|
|
127
127
|
Set Today
|
|
128
128
|
</Button>
|
|
129
|
-
<Button
|
|
130
|
-
|
|
129
|
+
<Button
|
|
130
|
+
type="outlined"
|
|
131
131
|
onPress={() => {
|
|
132
132
|
setBasicDate(null);
|
|
133
133
|
setRangeDate(null);
|
|
@@ -142,11 +142,11 @@ export const DatePickerExamples = () => {
|
|
|
142
142
|
|
|
143
143
|
{/* Date Time Range Picker Examples */}
|
|
144
144
|
<View spacing="md">
|
|
145
|
-
<Text size="
|
|
145
|
+
<Text size="md" weight="semibold">DateTimeRangePicker Examples</Text>
|
|
146
146
|
|
|
147
147
|
{/* Basic DateTime Range */}
|
|
148
148
|
<View spacing="sm">
|
|
149
|
-
<Text size="
|
|
149
|
+
<Text size="sm" weight="medium">Date and time range selection</Text>
|
|
150
150
|
<DateTimeRangePicker
|
|
151
151
|
value={dateTimeRange}
|
|
152
152
|
onChange={setDateTimeRange}
|
|
@@ -155,7 +155,7 @@ export const DatePickerExamples = () => {
|
|
|
155
155
|
helperText="Select date range first, then adjust times"
|
|
156
156
|
/>
|
|
157
157
|
{dateTimeRange?.startDate && dateTimeRange?.endDate && (
|
|
158
|
-
<Text size="
|
|
158
|
+
<Text size="sm" color="secondary">
|
|
159
159
|
Range: {dateTimeRange.startDate.toLocaleString()} to {dateTimeRange.endDate.toLocaleString()}
|
|
160
160
|
</Text>
|
|
161
161
|
)}
|
|
@@ -164,30 +164,30 @@ export const DatePickerExamples = () => {
|
|
|
164
164
|
|
|
165
165
|
{/* Features Description */}
|
|
166
166
|
<View spacing="md">
|
|
167
|
-
<Text size="
|
|
167
|
+
<Text size="md" weight="semibold">Features</Text>
|
|
168
168
|
<View spacing="sm">
|
|
169
|
-
<Text size="
|
|
169
|
+
<Text size="sm" color="secondary">
|
|
170
170
|
• Cross-platform calendar picker
|
|
171
171
|
</Text>
|
|
172
|
-
<Text size="
|
|
172
|
+
<Text size="sm" color="secondary">
|
|
173
173
|
• Date and time selection
|
|
174
174
|
</Text>
|
|
175
|
-
<Text size="
|
|
175
|
+
<Text size="sm" color="secondary">
|
|
176
176
|
• Date/time range selection
|
|
177
177
|
</Text>
|
|
178
|
-
<Text size="
|
|
178
|
+
<Text size="sm" color="secondary">
|
|
179
179
|
• 12/24 hour time formats
|
|
180
180
|
</Text>
|
|
181
|
-
<Text size="
|
|
181
|
+
<Text size="sm" color="secondary">
|
|
182
182
|
• Min/max date restrictions
|
|
183
183
|
</Text>
|
|
184
|
-
<Text size="
|
|
184
|
+
<Text size="sm" color="secondary">
|
|
185
185
|
• Accessible and keyboard navigable
|
|
186
186
|
</Text>
|
|
187
|
-
<Text size="
|
|
187
|
+
<Text size="sm" color="secondary">
|
|
188
188
|
• Theme-aware styling
|
|
189
189
|
</Text>
|
|
190
|
-
<Text size="
|
|
190
|
+
<Text size="sm" color="secondary">
|
|
191
191
|
• Customizable date/time formats
|
|
192
192
|
</Text>
|
|
193
193
|
</View>
|
|
@@ -1,42 +1,28 @@
|
|
|
1
|
+
import { Theme } from '@/theme';
|
|
1
2
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
type CalendarGridVariants = {
|
|
5
|
+
isCurrentMonth: boolean;
|
|
6
|
+
isSelected: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const calendarGridStyles = StyleSheet.create((theme: Theme) => ({
|
|
4
10
|
weekdayHeader: {
|
|
5
|
-
display: 'grid',
|
|
6
|
-
gridTemplateColumns: 'repeat(7, 1fr)',
|
|
7
|
-
gap: 2,
|
|
8
11
|
marginBottom: 8,
|
|
9
|
-
|
|
10
|
-
_web: {
|
|
11
|
-
display: 'grid',
|
|
12
|
-
gridTemplateColumns: 'repeat(7, 1fr)',
|
|
13
|
-
}
|
|
14
12
|
},
|
|
15
13
|
weekdayCell: {
|
|
16
14
|
alignItems: 'center',
|
|
17
15
|
justifyContent: 'center',
|
|
18
16
|
paddingVertical: 4,
|
|
19
|
-
|
|
20
|
-
_web: {
|
|
21
|
-
display: 'flex',
|
|
22
|
-
alignItems: 'center',
|
|
23
|
-
justifyContent: 'center',
|
|
24
|
-
}
|
|
25
17
|
},
|
|
26
18
|
weekdayText: {
|
|
27
19
|
fontSize: 12,
|
|
28
20
|
fontWeight: '500',
|
|
29
|
-
color: theme.colors
|
|
21
|
+
color: theme.colors.text.secondary,
|
|
30
22
|
},
|
|
31
23
|
calendarGrid: {
|
|
32
|
-
gap: 2,
|
|
33
24
|
marginBottom: 8,
|
|
34
25
|
height: 192,
|
|
35
|
-
|
|
36
|
-
_web: {
|
|
37
|
-
display: 'grid',
|
|
38
|
-
gridTemplateColumns: 'repeat(7, 1fr)',
|
|
39
|
-
}
|
|
40
26
|
},
|
|
41
27
|
dayCell: {
|
|
42
28
|
alignItems: 'center',
|
|
@@ -49,7 +35,7 @@ export const calendarGridStyles = StyleSheet.create((theme) => ({
|
|
|
49
35
|
justifyContent: 'center',
|
|
50
36
|
}
|
|
51
37
|
},
|
|
52
|
-
dayButton: {
|
|
38
|
+
dayButton: ({ isCurrentMonth, isSelected }: CalendarGridVariants) => ({
|
|
53
39
|
width: '100%',
|
|
54
40
|
height: '100%',
|
|
55
41
|
maxWidth: 36,
|
|
@@ -58,5 +44,8 @@ export const calendarGridStyles = StyleSheet.create((theme) => ({
|
|
|
58
44
|
padding: 0,
|
|
59
45
|
borderRadius: 4,
|
|
60
46
|
fontSize: 13,
|
|
61
|
-
|
|
47
|
+
opacity: isCurrentMonth ? 1 : 0.4,
|
|
48
|
+
backgroundColor: isSelected ? undefined : 'transparent',
|
|
49
|
+
color: isSelected ? undefined : theme.colors.text.primary,
|
|
50
|
+
}),
|
|
62
51
|
}));
|
|
@@ -96,7 +96,10 @@ export const CalendarGrid: React.FC<CalendarGridProps> = ({
|
|
|
96
96
|
return (
|
|
97
97
|
<>
|
|
98
98
|
{/* Weekday headers */}
|
|
99
|
-
<View style={
|
|
99
|
+
<View style={[
|
|
100
|
+
calendarGridStyles.weekdayHeader,
|
|
101
|
+
{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2 }
|
|
102
|
+
]}>
|
|
100
103
|
{['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((day) => (
|
|
101
104
|
<View key={day} style={calendarGridStyles.weekdayCell}>
|
|
102
105
|
<Text style={calendarGridStyles.weekdayText}>
|
|
@@ -107,25 +110,30 @@ export const CalendarGrid: React.FC<CalendarGridProps> = ({
|
|
|
107
110
|
</View>
|
|
108
111
|
|
|
109
112
|
{/* Calendar grid */}
|
|
110
|
-
<View
|
|
111
|
-
style={[
|
|
113
|
+
<View
|
|
114
|
+
style={[
|
|
115
|
+
calendarGridStyles.calendarGrid,
|
|
116
|
+
{
|
|
117
|
+
display: 'grid',
|
|
118
|
+
gridTemplateColumns: 'repeat(7, 1fr)',
|
|
119
|
+
gridTemplateRows: `repeat(${weekCount}, 1fr)`,
|
|
120
|
+
gap: 2
|
|
121
|
+
}
|
|
122
|
+
]}
|
|
112
123
|
>
|
|
113
124
|
{calendarDays.map((dayData, index) => {
|
|
114
125
|
const { date, isCurrentMonth } = dayData;
|
|
115
|
-
const
|
|
116
|
-
calendarGridStyles.dayButton,
|
|
117
|
-
{ opacity: isCurrentMonth ? 1 : 0.4 }
|
|
118
|
-
];
|
|
126
|
+
const isSelected = isDateSelected(date);
|
|
119
127
|
|
|
120
128
|
return (
|
|
121
129
|
<View key={index} style={calendarGridStyles.dayCell}>
|
|
122
130
|
<Button
|
|
123
|
-
|
|
124
|
-
intent={
|
|
131
|
+
type={isSelected ? 'contained' : 'text'}
|
|
132
|
+
intent={isSelected ? 'primary' : undefined}
|
|
125
133
|
disabled={isDateDisabled(date)}
|
|
126
134
|
onPress={() => handleDateSelect(date)}
|
|
127
|
-
size="
|
|
128
|
-
style={
|
|
135
|
+
size="sm"
|
|
136
|
+
style={calendarGridStyles.dayButton({ isCurrentMonth, isSelected })}
|
|
129
137
|
>
|
|
130
138
|
{date.getDate()}
|
|
131
139
|
</Button>
|
|
@@ -25,28 +25,28 @@ export const CalendarHeader: React.FC<CalendarHeaderProps> = ({
|
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<View style={calendarHeaderStyles.container}>
|
|
28
|
-
<Button
|
|
29
|
-
|
|
30
|
-
size="
|
|
31
|
-
onPress={onPreviousMonth}
|
|
28
|
+
<Button
|
|
29
|
+
type="text"
|
|
30
|
+
size="sm"
|
|
31
|
+
onPress={onPreviousMonth}
|
|
32
32
|
disabled={disabled}
|
|
33
33
|
style={calendarHeaderStyles.navButton}
|
|
34
34
|
>
|
|
35
35
|
←
|
|
36
36
|
</Button>
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
<View style={calendarHeaderStyles.centerSection}>
|
|
39
|
-
<Button
|
|
40
|
-
|
|
39
|
+
<Button
|
|
40
|
+
type="text"
|
|
41
41
|
onPress={onMonthClick}
|
|
42
42
|
disabled={disabled}
|
|
43
43
|
style={calendarHeaderStyles.titleButton}
|
|
44
44
|
>
|
|
45
45
|
<Text weight="semibold">{monthName}</Text>
|
|
46
46
|
</Button>
|
|
47
|
-
|
|
48
|
-
<Button
|
|
49
|
-
|
|
47
|
+
|
|
48
|
+
<Button
|
|
49
|
+
type="text"
|
|
50
50
|
onPress={onYearClick}
|
|
51
51
|
disabled={disabled}
|
|
52
52
|
style={calendarHeaderStyles.titleButton}
|
|
@@ -54,11 +54,11 @@ export const CalendarHeader: React.FC<CalendarHeaderProps> = ({
|
|
|
54
54
|
<Text weight="semibold">{year}</Text>
|
|
55
55
|
</Button>
|
|
56
56
|
</View>
|
|
57
|
-
|
|
58
|
-
<Button
|
|
59
|
-
|
|
60
|
-
size="
|
|
61
|
-
onPress={onNextMonth}
|
|
57
|
+
|
|
58
|
+
<Button
|
|
59
|
+
type="text"
|
|
60
|
+
size="sm"
|
|
61
|
+
onPress={onNextMonth}
|
|
62
62
|
disabled={disabled}
|
|
63
63
|
style={calendarHeaderStyles.navButton}
|
|
64
64
|
>
|