@idealyst/datepicker 1.2.119 → 11.2.121
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 +3 -3
- package/src/DateInput.native.tsx +33 -12
- package/src/DateInput.web.tsx +40 -17
- package/src/DatePicker.native.tsx +34 -5
- package/src/DatePicker.styles.ts +6 -4
- package/src/DatePicker.web.tsx +43 -14
- package/src/DateTimePicker.native.tsx +3 -0
- package/src/DateTimePicker.web.tsx +3 -0
- package/src/TimeInput.native.tsx +33 -12
- package/src/TimeInput.web.tsx +40 -17
- package/src/index.native.ts +1 -0
- package/src/index.ts +1 -0
- package/src/types.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/datepicker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.2.121",
|
|
4
4
|
"description": "Cross-platform date and time picker components for React and React Native",
|
|
5
5
|
"documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/datepicker#readme",
|
|
6
6
|
"readme": "README.md",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"publish:npm": "npm publish"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@idealyst/theme": "^
|
|
39
|
+
"@idealyst/theme": "^11.2.121",
|
|
40
40
|
"@mdi/js": ">=7.0.0",
|
|
41
41
|
"@mdi/react": ">=1.6.0",
|
|
42
42
|
"react": ">=16.8.0",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@idealyst/theme": "^
|
|
72
|
+
"@idealyst/theme": "^11.2.121",
|
|
73
73
|
"@mdi/js": "^7.4.47",
|
|
74
74
|
"@mdi/react": "^1.6.1",
|
|
75
75
|
"@types/react": "^19.1.0",
|
package/src/DateInput.native.tsx
CHANGED
|
@@ -13,6 +13,7 @@ export const DateInput: React.FC<DateInputProps> = ({
|
|
|
13
13
|
minDate,
|
|
14
14
|
maxDate,
|
|
15
15
|
disabled = false,
|
|
16
|
+
pressable = false,
|
|
16
17
|
error,
|
|
17
18
|
size = 'md',
|
|
18
19
|
style,
|
|
@@ -98,23 +99,43 @@ export const DateInput: React.FC<DateInputProps> = ({
|
|
|
98
99
|
{label}
|
|
99
100
|
</Text>
|
|
100
101
|
)}
|
|
101
|
-
|
|
102
|
-
<TextInput
|
|
103
|
-
value={inputValue}
|
|
104
|
-
onChangeText={handleInputChange}
|
|
105
|
-
onBlur={handleInputBlur}
|
|
106
|
-
placeholder={placeholder}
|
|
107
|
-
editable={!disabled}
|
|
108
|
-
style={textInputStyle}
|
|
109
|
-
/>
|
|
102
|
+
{pressable ? (
|
|
110
103
|
<TouchableOpacity
|
|
111
|
-
style={iconButtonStyle}
|
|
112
104
|
onPress={() => !disabled && setOpen(true)}
|
|
113
105
|
disabled={disabled}
|
|
106
|
+
activeOpacity={0.7}
|
|
114
107
|
>
|
|
115
|
-
<
|
|
108
|
+
<View style={inputContainerStyle} pointerEvents="none">
|
|
109
|
+
<TextInput
|
|
110
|
+
value={formatDate(value ?? undefined)}
|
|
111
|
+
placeholder={placeholder}
|
|
112
|
+
editable={false}
|
|
113
|
+
style={textInputStyle}
|
|
114
|
+
/>
|
|
115
|
+
<View style={iconButtonStyle}>
|
|
116
|
+
<MaterialDesignIcons name="calendar" size={iconStyle.width} style={iconStyle} />
|
|
117
|
+
</View>
|
|
118
|
+
</View>
|
|
116
119
|
</TouchableOpacity>
|
|
117
|
-
|
|
120
|
+
) : (
|
|
121
|
+
<View style={inputContainerStyle}>
|
|
122
|
+
<TextInput
|
|
123
|
+
value={inputValue}
|
|
124
|
+
onChangeText={handleInputChange}
|
|
125
|
+
onBlur={handleInputBlur}
|
|
126
|
+
placeholder={placeholder}
|
|
127
|
+
editable={!disabled}
|
|
128
|
+
style={textInputStyle}
|
|
129
|
+
/>
|
|
130
|
+
<TouchableOpacity
|
|
131
|
+
style={iconButtonStyle}
|
|
132
|
+
onPress={() => !disabled && setOpen(true)}
|
|
133
|
+
disabled={disabled}
|
|
134
|
+
>
|
|
135
|
+
<MaterialDesignIcons name="calendar" size={iconStyle.width} style={iconStyle} />
|
|
136
|
+
</TouchableOpacity>
|
|
137
|
+
</View>
|
|
138
|
+
)}
|
|
118
139
|
{error && (
|
|
119
140
|
<Text style={errorTextStyle}>
|
|
120
141
|
{error}
|
package/src/DateInput.web.tsx
CHANGED
|
@@ -18,6 +18,7 @@ export const DateInput: React.FC<DateInputProps> = ({
|
|
|
18
18
|
minDate,
|
|
19
19
|
maxDate,
|
|
20
20
|
disabled = false,
|
|
21
|
+
pressable = false,
|
|
21
22
|
error,
|
|
22
23
|
size = 'md',
|
|
23
24
|
style,
|
|
@@ -113,25 +114,47 @@ export const DateInput: React.FC<DateInputProps> = ({
|
|
|
113
114
|
{label && (
|
|
114
115
|
<span {...labelProps}>{label}</span>
|
|
115
116
|
)}
|
|
116
|
-
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
value={inputValue}
|
|
120
|
-
onChange={handleInputChange}
|
|
121
|
-
onBlur={handleInputBlur}
|
|
122
|
-
placeholder={placeholder}
|
|
123
|
-
disabled={disabled}
|
|
124
|
-
{...inputProps}
|
|
125
|
-
/>
|
|
126
|
-
<button
|
|
127
|
-
type="button"
|
|
128
|
-
{...iconButtonProps}
|
|
117
|
+
{pressable ? (
|
|
118
|
+
<div
|
|
119
|
+
ref={triggerRef}
|
|
129
120
|
onClick={() => !disabled && setOpen(!open)}
|
|
130
|
-
|
|
121
|
+
style={{ cursor: disabled ? 'not-allowed' : 'pointer' }}
|
|
131
122
|
>
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
<div {...containerProps} style={{ pointerEvents: 'none' }}>
|
|
124
|
+
<input
|
|
125
|
+
type="text"
|
|
126
|
+
value={formatDate(value ?? undefined)}
|
|
127
|
+
placeholder={placeholder}
|
|
128
|
+
readOnly
|
|
129
|
+
tabIndex={-1}
|
|
130
|
+
{...inputProps}
|
|
131
|
+
/>
|
|
132
|
+
<div {...iconButtonProps}>
|
|
133
|
+
<IconSvg path={mdiCalendar} size={iconSize} color={iconColor} />
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
) : (
|
|
138
|
+
<div {...containerProps} ref={triggerRef}>
|
|
139
|
+
<input
|
|
140
|
+
type="text"
|
|
141
|
+
value={inputValue}
|
|
142
|
+
onChange={handleInputChange}
|
|
143
|
+
onBlur={handleInputBlur}
|
|
144
|
+
placeholder={placeholder}
|
|
145
|
+
disabled={disabled}
|
|
146
|
+
{...inputProps}
|
|
147
|
+
/>
|
|
148
|
+
<button
|
|
149
|
+
type="button"
|
|
150
|
+
{...iconButtonProps}
|
|
151
|
+
onClick={() => !disabled && setOpen(!open)}
|
|
152
|
+
disabled={disabled}
|
|
153
|
+
>
|
|
154
|
+
<IconSvg path={mdiCalendar} size={iconSize} color={iconColor} />
|
|
155
|
+
</button>
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
135
158
|
{error && (
|
|
136
159
|
<span {...errorProps}>{error}</span>
|
|
137
160
|
)}
|
|
@@ -2,19 +2,27 @@ import React, { useMemo, useState } from 'react';
|
|
|
2
2
|
import { View, Text, TouchableOpacity } from 'react-native';
|
|
3
3
|
import MaterialDesignIcons from '@react-native-vector-icons/material-design-icons';
|
|
4
4
|
import { datePickerCalendarStyles } from './DatePicker.styles';
|
|
5
|
-
import type { DatePickerProps } from './types';
|
|
5
|
+
import type { DatePickerProps, DayIndicator } from './types';
|
|
6
6
|
|
|
7
7
|
const WEEKDAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
|
|
8
8
|
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
9
9
|
|
|
10
10
|
type ViewMode = 'calendar' | 'months' | 'years';
|
|
11
11
|
|
|
12
|
+
function formatDateKey(date: Date): string {
|
|
13
|
+
const y = date.getFullYear();
|
|
14
|
+
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
15
|
+
const d = String(date.getDate()).padStart(2, '0');
|
|
16
|
+
return `${y}-${m}-${d}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
export const DatePicker: React.FC<DatePickerProps> = ({
|
|
13
20
|
value,
|
|
14
21
|
onChange,
|
|
15
22
|
minDate,
|
|
16
23
|
maxDate,
|
|
17
24
|
disabled = false,
|
|
25
|
+
indicators,
|
|
18
26
|
style,
|
|
19
27
|
}) => {
|
|
20
28
|
const [currentMonth, setCurrentMonth] = useState(() => value || new Date());
|
|
@@ -44,6 +52,8 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
44
52
|
const selectorItemTextStyle = (styles.selectorItemText as any)({});
|
|
45
53
|
const selectorItemTextSelectedStyle = (styles.selectorItemTextSelected as any)({});
|
|
46
54
|
const iconStyle = (styles.iconColor as any)({});
|
|
55
|
+
const indicatorRowStyle = (styles.indicatorRow as any)({});
|
|
56
|
+
const indicatorStyle = (styles.indicator as any)({});
|
|
47
57
|
|
|
48
58
|
const { days, monthShort, year } = useMemo(() => {
|
|
49
59
|
const year = currentMonth.getFullYear();
|
|
@@ -157,6 +167,13 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
157
167
|
setCurrentMonth(new Date(currentMonth.getFullYear() + 10, currentMonth.getMonth(), 1));
|
|
158
168
|
};
|
|
159
169
|
|
|
170
|
+
// Helper to get indicators for a date
|
|
171
|
+
const getIndicators = (date: Date): DayIndicator[] => {
|
|
172
|
+
if (!indicators) return [];
|
|
173
|
+
const key = formatDateKey(date);
|
|
174
|
+
return indicators[key] || [];
|
|
175
|
+
};
|
|
176
|
+
|
|
160
177
|
// Render month selector
|
|
161
178
|
if (viewMode === 'months') {
|
|
162
179
|
return (
|
|
@@ -176,7 +193,7 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
176
193
|
>
|
|
177
194
|
<Text style={titleTextStyle}>{year}</Text>
|
|
178
195
|
</TouchableOpacity>
|
|
179
|
-
<View style={{ width:
|
|
196
|
+
<View style={{ width: 32 }} />
|
|
180
197
|
</View>
|
|
181
198
|
<View style={monthGridStyle}>
|
|
182
199
|
{MONTHS.map((month, index) => {
|
|
@@ -305,20 +322,24 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
305
322
|
const today = isToday(date);
|
|
306
323
|
const dayDisabled = isDisabled(date);
|
|
307
324
|
const disabledDayButtonStyle = (styles.dayButton as any)({ disabled: dayDisabled });
|
|
325
|
+
const dayIndicators = getIndicators(date);
|
|
308
326
|
|
|
309
327
|
return (
|
|
310
328
|
<View
|
|
311
329
|
key={index}
|
|
312
330
|
style={[
|
|
313
331
|
dayCellStyle,
|
|
314
|
-
selected && selectedDayStyle,
|
|
315
332
|
!isCurrentMonth && { opacity: 0.3 },
|
|
316
|
-
today && !selected && todayDayStyle,
|
|
317
333
|
dayDisabled && { opacity: 0.3 },
|
|
318
334
|
]}
|
|
319
335
|
>
|
|
320
336
|
<TouchableOpacity
|
|
321
|
-
style={[
|
|
337
|
+
style={[
|
|
338
|
+
dayButtonStyle,
|
|
339
|
+
dayDisabled && disabledDayButtonStyle,
|
|
340
|
+
selected && selectedDayStyle,
|
|
341
|
+
today && !selected && todayDayStyle,
|
|
342
|
+
]}
|
|
322
343
|
onPress={() => handleDayPress(date)}
|
|
323
344
|
disabled={dayDisabled}
|
|
324
345
|
>
|
|
@@ -331,6 +352,14 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
331
352
|
{date.getDate()}
|
|
332
353
|
</Text>
|
|
333
354
|
</TouchableOpacity>
|
|
355
|
+
<View style={indicatorRowStyle}>
|
|
356
|
+
{dayIndicators.slice(0, 3).map((ind, i) => (
|
|
357
|
+
<View
|
|
358
|
+
key={ind.key ?? i}
|
|
359
|
+
style={[indicatorStyle, { backgroundColor: ind.color }]}
|
|
360
|
+
/>
|
|
361
|
+
))}
|
|
362
|
+
</View>
|
|
334
363
|
</View>
|
|
335
364
|
);
|
|
336
365
|
})}
|
package/src/DatePicker.styles.ts
CHANGED
|
@@ -73,10 +73,12 @@ export const datePickerCalendarStyles = defineStyle('DatePickerCalendar', (theme
|
|
|
73
73
|
},
|
|
74
74
|
}),
|
|
75
75
|
|
|
76
|
-
// Calendar grid
|
|
76
|
+
// Calendar grid - fixed height so rows flex evenly regardless of 5 or 6 weeks
|
|
77
77
|
calendarGrid: (_props: DatePickerDynamicProps) => ({
|
|
78
78
|
flexDirection: 'row' as const,
|
|
79
79
|
flexWrap: 'wrap' as const,
|
|
80
|
+
height: 252, // 6 rows × 42px
|
|
81
|
+
alignContent: 'space-evenly' as const,
|
|
80
82
|
_web: {
|
|
81
83
|
display: 'flex',
|
|
82
84
|
},
|
|
@@ -263,12 +265,12 @@ export const datePickerCalendarStyles = defineStyle('DatePickerCalendar', (theme
|
|
|
263
265
|
},
|
|
264
266
|
}),
|
|
265
267
|
|
|
266
|
-
// Today styling - subtle background
|
|
268
|
+
// Today styling - subtle gray background
|
|
267
269
|
todayDay: (_props: DatePickerDynamicProps) => ({
|
|
268
|
-
backgroundColor: theme.intents.primary.light,
|
|
269
270
|
borderRadius: 16,
|
|
271
|
+
backgroundColor: theme.colors.pallet.gray?.[200] ?? theme.colors.surface.secondary,
|
|
270
272
|
_web: {
|
|
271
|
-
background: theme.
|
|
273
|
+
background: theme.colors.pallet.gray?.[200] ?? theme.colors.surface.secondary,
|
|
272
274
|
},
|
|
273
275
|
}),
|
|
274
276
|
|
package/src/DatePicker.web.tsx
CHANGED
|
@@ -3,19 +3,27 @@ import { getWebProps } from 'react-native-unistyles/web';
|
|
|
3
3
|
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
|
|
4
4
|
import { IconSvg } from './IconSvg.web';
|
|
5
5
|
import { datePickerCalendarStyles } from './DatePicker.styles';
|
|
6
|
-
import type { DatePickerProps } from './types';
|
|
6
|
+
import type { DatePickerProps, DayIndicator } from './types';
|
|
7
7
|
|
|
8
8
|
const WEEKDAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
|
|
9
9
|
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
10
10
|
|
|
11
11
|
type ViewMode = 'calendar' | 'months' | 'years';
|
|
12
12
|
|
|
13
|
+
function formatDateKey(date: Date): string {
|
|
14
|
+
const y = date.getFullYear();
|
|
15
|
+
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
16
|
+
const d = String(date.getDate()).padStart(2, '0');
|
|
17
|
+
return `${y}-${m}-${d}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
export const DatePicker: React.FC<DatePickerProps> = ({
|
|
14
21
|
value,
|
|
15
22
|
onChange,
|
|
16
23
|
minDate,
|
|
17
24
|
maxDate,
|
|
18
25
|
disabled = false,
|
|
26
|
+
indicators,
|
|
19
27
|
style,
|
|
20
28
|
}) => {
|
|
21
29
|
const [currentMonth, setCurrentMonth] = useState(() => value || new Date());
|
|
@@ -157,6 +165,8 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
157
165
|
const selectorItemTextStyle = (styles.selectorItemText as any)({});
|
|
158
166
|
const selectorItemTextSelectedStyle = (styles.selectorItemTextSelected as any)({});
|
|
159
167
|
const iconColorStyle = (styles.iconColor as any)({});
|
|
168
|
+
const indicatorRowStyle = (styles.indicatorRow as any)({});
|
|
169
|
+
const indicatorStyle = (styles.indicator as any)({});
|
|
160
170
|
|
|
161
171
|
// Get web props for all elements
|
|
162
172
|
const calendarProps = getWebProps([calendarStyle, style as any]);
|
|
@@ -174,6 +184,14 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
174
184
|
const selectorItemSelectedProps = getWebProps([selectorItemStyle, selectorItemSelectedStyle]);
|
|
175
185
|
const selectorItemTextProps = getWebProps([selectorItemTextStyle]);
|
|
176
186
|
const selectorItemTextSelectedProps = getWebProps([selectorItemTextStyle, selectorItemTextSelectedStyle]);
|
|
187
|
+
const indicatorRowProps = getWebProps([indicatorRowStyle]);
|
|
188
|
+
|
|
189
|
+
// Helper to get indicators for a date
|
|
190
|
+
const getIndicators = (date: Date): DayIndicator[] => {
|
|
191
|
+
if (!indicators) return [];
|
|
192
|
+
const key = formatDateKey(date);
|
|
193
|
+
return indicators[key] || [];
|
|
194
|
+
};
|
|
177
195
|
|
|
178
196
|
// Render month selector
|
|
179
197
|
if (viewMode === 'months') {
|
|
@@ -196,7 +214,7 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
196
214
|
>
|
|
197
215
|
<span {...titleTextProps}>{year}</span>
|
|
198
216
|
</button>
|
|
199
|
-
<div style={{ width:
|
|
217
|
+
<div style={{ width: 32 }} />
|
|
200
218
|
</div>
|
|
201
219
|
<div {...monthGridProps}>
|
|
202
220
|
{MONTHS.map((month, index) => {
|
|
@@ -332,6 +350,7 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
332
350
|
const selected = isSelected(date);
|
|
333
351
|
const today = isToday(date);
|
|
334
352
|
const dayDisabled = isDisabled(date);
|
|
353
|
+
const dayIndicators = getIndicators(date);
|
|
335
354
|
|
|
336
355
|
// Get appropriate button props (className and ref only)
|
|
337
356
|
const buttonProps = dayDisabled
|
|
@@ -343,18 +362,28 @@ export const DatePicker: React.FC<DatePickerProps> = ({
|
|
|
343
362
|
: dayButtonProps;
|
|
344
363
|
|
|
345
364
|
return (
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
365
|
+
<div key={index} {...dayCellProps}>
|
|
366
|
+
<button
|
|
367
|
+
type="button"
|
|
368
|
+
className={buttonProps.className}
|
|
369
|
+
style={{ opacity: (!isCurrentMonthDay || dayDisabled) ? 0.3 : 1 }}
|
|
370
|
+
onClick={() => handleDayPress(date)}
|
|
371
|
+
disabled={dayDisabled}
|
|
372
|
+
>
|
|
373
|
+
<span {...(selected ? selectedDayTextProps : dayTextProps)}>
|
|
374
|
+
{date.getDate()}
|
|
375
|
+
</span>
|
|
376
|
+
</button>
|
|
377
|
+
<div {...indicatorRowProps}>
|
|
378
|
+
{dayIndicators.slice(0, 3).map((ind, i) => (
|
|
379
|
+
<div
|
|
380
|
+
key={ind.key ?? i}
|
|
381
|
+
className={getWebProps([indicatorStyle]).className}
|
|
382
|
+
style={{ backgroundColor: ind.color }}
|
|
383
|
+
/>
|
|
384
|
+
))}
|
|
385
|
+
</div>
|
|
386
|
+
</div>
|
|
358
387
|
);
|
|
359
388
|
})}
|
|
360
389
|
</div>
|
|
@@ -14,6 +14,7 @@ export const DateTimePicker: React.FC<DateTimePickerProps> = ({
|
|
|
14
14
|
timeMode = '12h',
|
|
15
15
|
minuteStep = 1,
|
|
16
16
|
disabled = false,
|
|
17
|
+
pressable = false,
|
|
17
18
|
error,
|
|
18
19
|
size = 'md',
|
|
19
20
|
style,
|
|
@@ -91,6 +92,7 @@ export const DateTimePicker: React.FC<DateTimePickerProps> = ({
|
|
|
91
92
|
minDate={minDate}
|
|
92
93
|
maxDate={maxDate}
|
|
93
94
|
disabled={disabled}
|
|
95
|
+
pressable={pressable}
|
|
94
96
|
error={error}
|
|
95
97
|
size={size}
|
|
96
98
|
/>
|
|
@@ -103,6 +105,7 @@ export const DateTimePicker: React.FC<DateTimePickerProps> = ({
|
|
|
103
105
|
mode={timeMode}
|
|
104
106
|
minuteStep={minuteStep}
|
|
105
107
|
disabled={disabled}
|
|
108
|
+
pressable={pressable}
|
|
106
109
|
size={size}
|
|
107
110
|
/>
|
|
108
111
|
</View>
|
|
@@ -14,6 +14,7 @@ export const DateTimePicker: React.FC<DateTimePickerProps> = ({
|
|
|
14
14
|
timeMode = '12h',
|
|
15
15
|
minuteStep = 1,
|
|
16
16
|
disabled = false,
|
|
17
|
+
pressable = false,
|
|
17
18
|
error,
|
|
18
19
|
size = 'md',
|
|
19
20
|
style,
|
|
@@ -95,6 +96,7 @@ export const DateTimePicker: React.FC<DateTimePickerProps> = ({
|
|
|
95
96
|
minDate={minDate}
|
|
96
97
|
maxDate={maxDate}
|
|
97
98
|
disabled={disabled}
|
|
99
|
+
pressable={pressable}
|
|
98
100
|
error={error}
|
|
99
101
|
size={size}
|
|
100
102
|
/>
|
|
@@ -107,6 +109,7 @@ export const DateTimePicker: React.FC<DateTimePickerProps> = ({
|
|
|
107
109
|
mode={timeMode}
|
|
108
110
|
minuteStep={minuteStep}
|
|
109
111
|
disabled={disabled}
|
|
112
|
+
pressable={pressable}
|
|
110
113
|
size={size}
|
|
111
114
|
/>
|
|
112
115
|
</div>
|
package/src/TimeInput.native.tsx
CHANGED
|
@@ -13,6 +13,7 @@ export const TimeInput: React.FC<TimeInputProps> = ({
|
|
|
13
13
|
mode = '12h',
|
|
14
14
|
minuteStep = 1,
|
|
15
15
|
disabled = false,
|
|
16
|
+
pressable = false,
|
|
16
17
|
error,
|
|
17
18
|
size = 'md',
|
|
18
19
|
style,
|
|
@@ -118,23 +119,43 @@ export const TimeInput: React.FC<TimeInputProps> = ({
|
|
|
118
119
|
{label}
|
|
119
120
|
</Text>
|
|
120
121
|
)}
|
|
121
|
-
|
|
122
|
-
<TextInput
|
|
123
|
-
value={inputValue}
|
|
124
|
-
onChangeText={handleInputChange}
|
|
125
|
-
onBlur={handleInputBlur}
|
|
126
|
-
placeholder={placeholder}
|
|
127
|
-
editable={!disabled}
|
|
128
|
-
style={textInputStyle}
|
|
129
|
-
/>
|
|
122
|
+
{pressable ? (
|
|
130
123
|
<TouchableOpacity
|
|
131
|
-
style={iconButtonStyle}
|
|
132
124
|
onPress={() => !disabled && setOpen(true)}
|
|
133
125
|
disabled={disabled}
|
|
126
|
+
activeOpacity={0.7}
|
|
134
127
|
>
|
|
135
|
-
<
|
|
128
|
+
<View style={inputContainerStyle} pointerEvents="none">
|
|
129
|
+
<TextInput
|
|
130
|
+
value={formatTime(value ?? undefined)}
|
|
131
|
+
placeholder={placeholder}
|
|
132
|
+
editable={false}
|
|
133
|
+
style={textInputStyle}
|
|
134
|
+
/>
|
|
135
|
+
<View style={iconButtonStyle}>
|
|
136
|
+
<MaterialDesignIcons name="clock-outline" size={iconStyle.width} style={iconStyle} />
|
|
137
|
+
</View>
|
|
138
|
+
</View>
|
|
136
139
|
</TouchableOpacity>
|
|
137
|
-
|
|
140
|
+
) : (
|
|
141
|
+
<View style={inputContainerStyle}>
|
|
142
|
+
<TextInput
|
|
143
|
+
value={inputValue}
|
|
144
|
+
onChangeText={handleInputChange}
|
|
145
|
+
onBlur={handleInputBlur}
|
|
146
|
+
placeholder={placeholder}
|
|
147
|
+
editable={!disabled}
|
|
148
|
+
style={textInputStyle}
|
|
149
|
+
/>
|
|
150
|
+
<TouchableOpacity
|
|
151
|
+
style={iconButtonStyle}
|
|
152
|
+
onPress={() => !disabled && setOpen(true)}
|
|
153
|
+
disabled={disabled}
|
|
154
|
+
>
|
|
155
|
+
<MaterialDesignIcons name="clock-outline" size={iconStyle.width} style={iconStyle} />
|
|
156
|
+
</TouchableOpacity>
|
|
157
|
+
</View>
|
|
158
|
+
)}
|
|
138
159
|
{error && (
|
|
139
160
|
<Text style={errorTextStyle}>
|
|
140
161
|
{error}
|
package/src/TimeInput.web.tsx
CHANGED
|
@@ -17,6 +17,7 @@ export const TimeInput: React.FC<TimeInputProps> = ({
|
|
|
17
17
|
mode = '12h',
|
|
18
18
|
minuteStep = 1,
|
|
19
19
|
disabled = false,
|
|
20
|
+
pressable = false,
|
|
20
21
|
error,
|
|
21
22
|
size = 'md',
|
|
22
23
|
style,
|
|
@@ -137,25 +138,47 @@ export const TimeInput: React.FC<TimeInputProps> = ({
|
|
|
137
138
|
{label && (
|
|
138
139
|
<span {...labelProps}>{label}</span>
|
|
139
140
|
)}
|
|
140
|
-
|
|
141
|
-
<
|
|
142
|
-
|
|
143
|
-
value={inputValue}
|
|
144
|
-
onChange={handleInputChange}
|
|
145
|
-
onBlur={handleInputBlur}
|
|
146
|
-
placeholder={placeholder}
|
|
147
|
-
disabled={disabled}
|
|
148
|
-
{...inputProps}
|
|
149
|
-
/>
|
|
150
|
-
<button
|
|
151
|
-
type="button"
|
|
152
|
-
{...iconButtonProps}
|
|
141
|
+
{pressable ? (
|
|
142
|
+
<div
|
|
143
|
+
ref={triggerRef}
|
|
153
144
|
onClick={() => !disabled && setOpen(!open)}
|
|
154
|
-
|
|
145
|
+
style={{ cursor: disabled ? 'not-allowed' : 'pointer' }}
|
|
155
146
|
>
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
147
|
+
<div {...containerProps} style={{ pointerEvents: 'none' }}>
|
|
148
|
+
<input
|
|
149
|
+
type="text"
|
|
150
|
+
value={formatTime(value ?? undefined)}
|
|
151
|
+
placeholder={placeholder}
|
|
152
|
+
readOnly
|
|
153
|
+
tabIndex={-1}
|
|
154
|
+
{...inputProps}
|
|
155
|
+
/>
|
|
156
|
+
<div {...iconButtonProps}>
|
|
157
|
+
<IconSvg path={mdiClockOutline} size={iconSize} color={iconColor} />
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
) : (
|
|
162
|
+
<div {...containerProps} ref={triggerRef}>
|
|
163
|
+
<input
|
|
164
|
+
type="text"
|
|
165
|
+
value={inputValue}
|
|
166
|
+
onChange={handleInputChange}
|
|
167
|
+
onBlur={handleInputBlur}
|
|
168
|
+
placeholder={placeholder}
|
|
169
|
+
disabled={disabled}
|
|
170
|
+
{...inputProps}
|
|
171
|
+
/>
|
|
172
|
+
<button
|
|
173
|
+
type="button"
|
|
174
|
+
{...iconButtonProps}
|
|
175
|
+
onClick={() => !disabled && setOpen(!open)}
|
|
176
|
+
disabled={disabled}
|
|
177
|
+
>
|
|
178
|
+
<IconSvg path={mdiClockOutline} size={iconSize} color={iconColor} />
|
|
179
|
+
</button>
|
|
180
|
+
</div>
|
|
181
|
+
)}
|
|
159
182
|
{error && (
|
|
160
183
|
<span {...errorProps}>{error}</span>
|
|
161
184
|
)}
|
package/src/index.native.ts
CHANGED
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -34,6 +34,8 @@ export interface DateInputProps {
|
|
|
34
34
|
minDate?: Date;
|
|
35
35
|
maxDate?: Date;
|
|
36
36
|
disabled?: boolean;
|
|
37
|
+
/** When true, the entire input area is pressable to open the calendar instead of being a text input. */
|
|
38
|
+
pressable?: boolean;
|
|
37
39
|
error?: string;
|
|
38
40
|
size?: Size;
|
|
39
41
|
style?: ViewStyle;
|
|
@@ -47,6 +49,8 @@ export interface TimeInputProps {
|
|
|
47
49
|
mode?: '12h' | '24h';
|
|
48
50
|
minuteStep?: number;
|
|
49
51
|
disabled?: boolean;
|
|
52
|
+
/** When true, the entire input area is pressable to open the time picker instead of being a text input. */
|
|
53
|
+
pressable?: boolean;
|
|
50
54
|
error?: string;
|
|
51
55
|
size?: Size;
|
|
52
56
|
style?: ViewStyle;
|
|
@@ -61,6 +65,8 @@ export interface DateTimePickerProps {
|
|
|
61
65
|
timeMode?: '12h' | '24h';
|
|
62
66
|
minuteStep?: number;
|
|
63
67
|
disabled?: boolean;
|
|
68
|
+
/** When true, both input areas are pressable to open their pickers instead of being text inputs. */
|
|
69
|
+
pressable?: boolean;
|
|
64
70
|
error?: string;
|
|
65
71
|
size?: Size;
|
|
66
72
|
style?: ViewStyle;
|