@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,195 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text } from '@idealyst/components';
|
|
3
|
-
import { TouchableOpacity } from 'react-native';
|
|
4
|
-
import Svg, { Circle, Line } from 'react-native-svg';
|
|
5
|
-
import { timePickerStyles } from '../TimePicker.styles';
|
|
6
|
-
|
|
7
|
-
interface ClockFaceProps {
|
|
8
|
-
activeSelection: 'hour' | 'minute';
|
|
9
|
-
hours: number;
|
|
10
|
-
minutes: number;
|
|
11
|
-
displayHours: number;
|
|
12
|
-
mode: '12h' | '24h';
|
|
13
|
-
disabled: boolean;
|
|
14
|
-
onHourClick: (hour: number) => void;
|
|
15
|
-
onMinuteClick: (minute: number) => void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const ClockFace: React.FC<ClockFaceProps> = ({
|
|
19
|
-
activeSelection,
|
|
20
|
-
hours,
|
|
21
|
-
minutes,
|
|
22
|
-
displayHours,
|
|
23
|
-
mode,
|
|
24
|
-
disabled,
|
|
25
|
-
onHourClick,
|
|
26
|
-
onMinuteClick,
|
|
27
|
-
}) => {
|
|
28
|
-
// Clock configuration
|
|
29
|
-
const CLOCK_SIZE = 180;
|
|
30
|
-
const CENTER = CLOCK_SIZE / 2;
|
|
31
|
-
const CLOCK_RADIUS = CENTER - 5;
|
|
32
|
-
const NUMBER_RADIUS = CENTER - 24;
|
|
33
|
-
const HOUR_HAND_LENGTH = CENTER - 44;
|
|
34
|
-
const MINUTE_HAND_LENGTH = CENTER - 36;
|
|
35
|
-
const CIRCLE_RADIUS = 15;
|
|
36
|
-
|
|
37
|
-
if (activeSelection === 'hour') {
|
|
38
|
-
return (
|
|
39
|
-
<View style={[timePickerStyles.clockContainer, { position: 'relative' }]}>
|
|
40
|
-
<Svg width={CLOCK_SIZE} height={CLOCK_SIZE} style={timePickerStyles.clockSvg}>
|
|
41
|
-
{/* Clock face */}
|
|
42
|
-
<Circle
|
|
43
|
-
cx={CENTER}
|
|
44
|
-
cy={CENTER}
|
|
45
|
-
r={CLOCK_RADIUS}
|
|
46
|
-
fill="#f9fafb"
|
|
47
|
-
stroke="#e5e7eb"
|
|
48
|
-
strokeWidth="2"
|
|
49
|
-
/>
|
|
50
|
-
|
|
51
|
-
{/* Hour hand pointing to selected hour */}
|
|
52
|
-
{(() => {
|
|
53
|
-
const selectedHour = mode === '12h' ? displayHours : hours;
|
|
54
|
-
const hourFor12Clock = selectedHour === 12 ? 0 : selectedHour;
|
|
55
|
-
const hourAngle = (hourFor12Clock * 30) - 90;
|
|
56
|
-
const handX = CENTER + HOUR_HAND_LENGTH * Math.cos(hourAngle * Math.PI / 180);
|
|
57
|
-
const handY = CENTER + HOUR_HAND_LENGTH * Math.sin(hourAngle * Math.PI / 180);
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<Line
|
|
61
|
-
x1={CENTER}
|
|
62
|
-
y1={CENTER}
|
|
63
|
-
x2={handX}
|
|
64
|
-
y2={handY}
|
|
65
|
-
stroke="#3b82f6"
|
|
66
|
-
strokeWidth="3"
|
|
67
|
-
strokeLinecap="round"
|
|
68
|
-
/>
|
|
69
|
-
);
|
|
70
|
-
})()}
|
|
71
|
-
|
|
72
|
-
{/* Center dot */}
|
|
73
|
-
<Circle cx={CENTER} cy={CENTER} r="4" fill="#3b82f6"/>
|
|
74
|
-
</Svg>
|
|
75
|
-
|
|
76
|
-
{/* TouchableOpacity buttons for hour numbers */}
|
|
77
|
-
{[...Array(12)].map((_, i) => {
|
|
78
|
-
const hour = i === 0 ? 12 : i;
|
|
79
|
-
const angle = (i * 30) - 90;
|
|
80
|
-
const x = CENTER + NUMBER_RADIUS * Math.cos(angle * Math.PI / 180);
|
|
81
|
-
const y = CENTER + NUMBER_RADIUS * Math.sin(angle * Math.PI / 180);
|
|
82
|
-
const isSelected = (mode === '12h' ? displayHours : hours) === (hour === 12 ? (mode === '12h' ? 12 : 0) : hour);
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<TouchableOpacity
|
|
86
|
-
key={`touch-${i}`}
|
|
87
|
-
onPressIn={() => !disabled && onHourClick(hour)}
|
|
88
|
-
disabled={disabled}
|
|
89
|
-
style={{
|
|
90
|
-
position: 'absolute',
|
|
91
|
-
left: x - CIRCLE_RADIUS,
|
|
92
|
-
top: y - CIRCLE_RADIUS,
|
|
93
|
-
width: CIRCLE_RADIUS * 2,
|
|
94
|
-
height: CIRCLE_RADIUS * 2,
|
|
95
|
-
borderRadius: CIRCLE_RADIUS,
|
|
96
|
-
backgroundColor: isSelected ? '#3b82f6' : 'transparent',
|
|
97
|
-
borderWidth: 1,
|
|
98
|
-
borderColor: isSelected ? '#3b82f6' : '#e5e7eb',
|
|
99
|
-
justifyContent: 'center',
|
|
100
|
-
alignItems: 'center',
|
|
101
|
-
}}
|
|
102
|
-
>
|
|
103
|
-
<Text style={{
|
|
104
|
-
fontSize: 14,
|
|
105
|
-
fontWeight: '500',
|
|
106
|
-
color: isSelected ? '#ffffff' : '#374151',
|
|
107
|
-
textAlign: 'center',
|
|
108
|
-
}}>
|
|
109
|
-
{hour}
|
|
110
|
-
</Text>
|
|
111
|
-
</TouchableOpacity>
|
|
112
|
-
);
|
|
113
|
-
})}
|
|
114
|
-
</View>
|
|
115
|
-
);
|
|
116
|
-
} else {
|
|
117
|
-
// Minute selection clock
|
|
118
|
-
return (
|
|
119
|
-
<View style={[timePickerStyles.clockContainer, { position: 'relative' }]}>
|
|
120
|
-
<Svg width={CLOCK_SIZE} height={CLOCK_SIZE} style={timePickerStyles.clockSvg}>
|
|
121
|
-
{/* Clock face */}
|
|
122
|
-
<Circle
|
|
123
|
-
cx={CENTER}
|
|
124
|
-
cy={CENTER}
|
|
125
|
-
r={CLOCK_RADIUS}
|
|
126
|
-
fill="#f9fafb"
|
|
127
|
-
stroke="#e5e7eb"
|
|
128
|
-
strokeWidth="2"
|
|
129
|
-
/>
|
|
130
|
-
|
|
131
|
-
{/* Minute hand */}
|
|
132
|
-
{(() => {
|
|
133
|
-
const minuteAngle = (minutes * 6) - 90;
|
|
134
|
-
const handX = CENTER + MINUTE_HAND_LENGTH * Math.cos(minuteAngle * Math.PI / 180);
|
|
135
|
-
const handY = CENTER + MINUTE_HAND_LENGTH * Math.sin(minuteAngle * Math.PI / 180);
|
|
136
|
-
|
|
137
|
-
return (
|
|
138
|
-
<Line
|
|
139
|
-
x1={CENTER}
|
|
140
|
-
y1={CENTER}
|
|
141
|
-
x2={handX}
|
|
142
|
-
y2={handY}
|
|
143
|
-
stroke="#3b82f6"
|
|
144
|
-
strokeWidth="3"
|
|
145
|
-
strokeLinecap="round"
|
|
146
|
-
/>
|
|
147
|
-
);
|
|
148
|
-
})()}
|
|
149
|
-
|
|
150
|
-
{/* Center dot */}
|
|
151
|
-
<Circle cx={CENTER} cy={CENTER} r="4" fill="#3b82f6"/>
|
|
152
|
-
</Svg>
|
|
153
|
-
|
|
154
|
-
{/* TouchableOpacity buttons for minute numbers */}
|
|
155
|
-
{[...Array(12)].map((_, i) => {
|
|
156
|
-
const minute = i * 5;
|
|
157
|
-
const angle = (i * 30) - 90;
|
|
158
|
-
const x = CENTER + NUMBER_RADIUS * Math.cos(angle * Math.PI / 180);
|
|
159
|
-
const y = CENTER + NUMBER_RADIUS * Math.sin(angle * Math.PI / 180);
|
|
160
|
-
const isSelected = Math.floor(minutes / 5) * 5 === minute;
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<TouchableOpacity
|
|
164
|
-
key={`touch-${i}`}
|
|
165
|
-
onPressIn={() => !disabled && onMinuteClick(minute)}
|
|
166
|
-
disabled={disabled}
|
|
167
|
-
style={{
|
|
168
|
-
position: 'absolute',
|
|
169
|
-
left: x - CIRCLE_RADIUS,
|
|
170
|
-
top: y - CIRCLE_RADIUS,
|
|
171
|
-
width: CIRCLE_RADIUS * 2,
|
|
172
|
-
height: CIRCLE_RADIUS * 2,
|
|
173
|
-
borderRadius: CIRCLE_RADIUS,
|
|
174
|
-
backgroundColor: isSelected ? '#3b82f6' : 'transparent',
|
|
175
|
-
borderWidth: 1,
|
|
176
|
-
borderColor: isSelected ? '#3b82f6' : '#e5e7eb',
|
|
177
|
-
justifyContent: 'center',
|
|
178
|
-
alignItems: 'center',
|
|
179
|
-
}}
|
|
180
|
-
>
|
|
181
|
-
<Text style={{
|
|
182
|
-
fontSize: 14,
|
|
183
|
-
fontWeight: '500',
|
|
184
|
-
color: isSelected ? '#ffffff' : '#374151',
|
|
185
|
-
textAlign: 'center',
|
|
186
|
-
}}>
|
|
187
|
-
{String(minute).padStart(2, '0')}
|
|
188
|
-
</Text>
|
|
189
|
-
</TouchableOpacity>
|
|
190
|
-
);
|
|
191
|
-
})}
|
|
192
|
-
</View>
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
};
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from '@idealyst/components';
|
|
3
|
-
import { timePickerStyles } from '../TimePicker.styles';
|
|
4
|
-
|
|
5
|
-
interface ClockFaceProps {
|
|
6
|
-
activeSelection: 'hour' | 'minute';
|
|
7
|
-
hours: number;
|
|
8
|
-
minutes: number;
|
|
9
|
-
displayHours: number;
|
|
10
|
-
mode: '12h' | '24h';
|
|
11
|
-
disabled: boolean;
|
|
12
|
-
onHourClick: (hour: number) => void;
|
|
13
|
-
onMinuteClick: (minute: number) => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const ClockFace: React.FC<ClockFaceProps> = ({
|
|
17
|
-
activeSelection,
|
|
18
|
-
hours,
|
|
19
|
-
minutes,
|
|
20
|
-
displayHours,
|
|
21
|
-
mode,
|
|
22
|
-
disabled,
|
|
23
|
-
onHourClick,
|
|
24
|
-
onMinuteClick,
|
|
25
|
-
}) => {
|
|
26
|
-
// Clock configuration
|
|
27
|
-
const CLOCK_SIZE = 180;
|
|
28
|
-
const CENTER = CLOCK_SIZE / 2;
|
|
29
|
-
const CLOCK_RADIUS = CENTER - 5;
|
|
30
|
-
const NUMBER_RADIUS = CENTER - 24;
|
|
31
|
-
const HOUR_HAND_LENGTH = CENTER - 44;
|
|
32
|
-
const MINUTE_HAND_LENGTH = CENTER - 36;
|
|
33
|
-
const CIRCLE_RADIUS = 15;
|
|
34
|
-
|
|
35
|
-
if (activeSelection === 'hour') {
|
|
36
|
-
return (
|
|
37
|
-
<View style={timePickerStyles.clockContainer}>
|
|
38
|
-
<svg width={CLOCK_SIZE} height={CLOCK_SIZE} style={timePickerStyles.clockSvg}>
|
|
39
|
-
{/* Clock face */}
|
|
40
|
-
<circle cx={CENTER} cy={CENTER} r={CLOCK_RADIUS} fill="#f9fafb" stroke="#e5e7eb" strokeWidth="2"/>
|
|
41
|
-
|
|
42
|
-
{/* Hour numbers - clickable */}
|
|
43
|
-
{[...Array(12)].map((_, i) => {
|
|
44
|
-
const hour = i === 0 ? 12 : i;
|
|
45
|
-
const angle = (i * 30) - 90;
|
|
46
|
-
const x = CENTER + NUMBER_RADIUS * Math.cos(angle * Math.PI / 180);
|
|
47
|
-
const y = CENTER + NUMBER_RADIUS * Math.sin(angle * Math.PI / 180);
|
|
48
|
-
const isSelected = (mode === '12h' ? displayHours : hours) === (hour === 12 ? (mode === '12h' ? 12 : 0) : hour);
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<g key={i} onClick={() => !disabled && onHourClick(hour)}>
|
|
52
|
-
<circle
|
|
53
|
-
cx={x}
|
|
54
|
-
cy={y}
|
|
55
|
-
r={CIRCLE_RADIUS}
|
|
56
|
-
fill={isSelected ? '#3b82f6' : 'transparent'}
|
|
57
|
-
stroke={isSelected ? '#3b82f6' : '#e5e7eb'}
|
|
58
|
-
strokeWidth="1"
|
|
59
|
-
style={{ cursor: disabled ? 'default' : 'pointer' }}
|
|
60
|
-
/>
|
|
61
|
-
<text
|
|
62
|
-
x={x}
|
|
63
|
-
y={y + 4}
|
|
64
|
-
textAnchor="middle"
|
|
65
|
-
fontSize="14"
|
|
66
|
-
fill={isSelected ? '#ffffff' : '#374151'}
|
|
67
|
-
fontWeight="500"
|
|
68
|
-
style={{ cursor: disabled ? 'default' : 'pointer', userSelect: 'none', pointerEvents: 'none' }}
|
|
69
|
-
>
|
|
70
|
-
{hour}
|
|
71
|
-
</text>
|
|
72
|
-
</g>
|
|
73
|
-
);
|
|
74
|
-
})}
|
|
75
|
-
|
|
76
|
-
{/* Hour hand pointing to selected hour */}
|
|
77
|
-
{(() => {
|
|
78
|
-
const selectedHour = mode === '12h' ? displayHours : hours;
|
|
79
|
-
const hourFor12Clock = selectedHour === 12 ? 0 : selectedHour;
|
|
80
|
-
const hourAngle = (hourFor12Clock * 30) - 90;
|
|
81
|
-
const handX = CENTER + HOUR_HAND_LENGTH * Math.cos(hourAngle * Math.PI / 180);
|
|
82
|
-
const handY = CENTER + HOUR_HAND_LENGTH * Math.sin(hourAngle * Math.PI / 180);
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<line
|
|
86
|
-
x1={CENTER}
|
|
87
|
-
y1={CENTER}
|
|
88
|
-
x2={handX}
|
|
89
|
-
y2={handY}
|
|
90
|
-
stroke="#3b82f6"
|
|
91
|
-
strokeWidth="3"
|
|
92
|
-
strokeLinecap="round"
|
|
93
|
-
/>
|
|
94
|
-
);
|
|
95
|
-
})()}
|
|
96
|
-
|
|
97
|
-
{/* Center dot */}
|
|
98
|
-
<circle cx={CENTER} cy={CENTER} r="4" fill="#3b82f6"/>
|
|
99
|
-
</svg>
|
|
100
|
-
</View>
|
|
101
|
-
);
|
|
102
|
-
} else {
|
|
103
|
-
return (
|
|
104
|
-
<View style={timePickerStyles.clockContainer}>
|
|
105
|
-
<svg width={CLOCK_SIZE} height={CLOCK_SIZE} style={timePickerStyles.clockSvg}>
|
|
106
|
-
{/* Clock face */}
|
|
107
|
-
<circle cx={CENTER} cy={CENTER} r={CLOCK_RADIUS} fill="#f9fafb" stroke="#e5e7eb" strokeWidth="2"/>
|
|
108
|
-
|
|
109
|
-
{/* Minute markers - every 5 minutes */}
|
|
110
|
-
{[...Array(12)].map((_, i) => {
|
|
111
|
-
const minute = i * 5;
|
|
112
|
-
const angle = (i * 30) - 90;
|
|
113
|
-
const x = CENTER + NUMBER_RADIUS * Math.cos(angle * Math.PI / 180);
|
|
114
|
-
const y = CENTER + NUMBER_RADIUS * Math.sin(angle * Math.PI / 180);
|
|
115
|
-
const isSelected = Math.floor(minutes / 5) * 5 === minute;
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<g key={i} onClick={() => !disabled && onMinuteClick(minute)}>
|
|
119
|
-
<circle
|
|
120
|
-
cx={x}
|
|
121
|
-
cy={y}
|
|
122
|
-
r={CIRCLE_RADIUS}
|
|
123
|
-
fill={isSelected ? '#3b82f6' : 'transparent'}
|
|
124
|
-
stroke={isSelected ? '#3b82f6' : '#e5e7eb'}
|
|
125
|
-
strokeWidth="1"
|
|
126
|
-
style={{ cursor: disabled ? 'default' : 'pointer' }}
|
|
127
|
-
/>
|
|
128
|
-
<text
|
|
129
|
-
x={x}
|
|
130
|
-
y={y + 4}
|
|
131
|
-
textAnchor="middle"
|
|
132
|
-
fontSize="12"
|
|
133
|
-
fill={isSelected ? '#ffffff' : '#374151'}
|
|
134
|
-
fontWeight="500"
|
|
135
|
-
style={{ cursor: disabled ? 'default' : 'pointer', userSelect: 'none', pointerEvents: 'none' }}
|
|
136
|
-
>
|
|
137
|
-
{minute.toString().padStart(2, '0')}
|
|
138
|
-
</text>
|
|
139
|
-
</g>
|
|
140
|
-
);
|
|
141
|
-
})}
|
|
142
|
-
|
|
143
|
-
{/* Minute hand pointing to selected minute */}
|
|
144
|
-
{(() => {
|
|
145
|
-
const minuteAngle = (minutes * 6) - 90;
|
|
146
|
-
const handX = CENTER + MINUTE_HAND_LENGTH * Math.cos(minuteAngle * Math.PI / 180);
|
|
147
|
-
const handY = CENTER + MINUTE_HAND_LENGTH * Math.sin(minuteAngle * Math.PI / 180);
|
|
148
|
-
|
|
149
|
-
return (
|
|
150
|
-
<line
|
|
151
|
-
x1={CENTER}
|
|
152
|
-
y1={CENTER}
|
|
153
|
-
x2={handX}
|
|
154
|
-
y2={handY}
|
|
155
|
-
stroke="#3b82f6"
|
|
156
|
-
strokeWidth="2"
|
|
157
|
-
strokeLinecap="round"
|
|
158
|
-
/>
|
|
159
|
-
);
|
|
160
|
-
})()}
|
|
161
|
-
|
|
162
|
-
{/* Center dot */}
|
|
163
|
-
<circle cx={CENTER} cy={CENTER} r="4" fill="#3b82f6"/>
|
|
164
|
-
</svg>
|
|
165
|
-
</View>
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { TextInput } from 'react-native';
|
|
3
|
-
import { timePickerStyles } from '../TimePicker.styles';
|
|
4
|
-
|
|
5
|
-
interface TimeInputProps {
|
|
6
|
-
type: 'hour' | 'minute';
|
|
7
|
-
value: string;
|
|
8
|
-
onChangeText: (value: string) => void;
|
|
9
|
-
onFocus: () => void;
|
|
10
|
-
onBlur: () => void;
|
|
11
|
-
isActive: boolean;
|
|
12
|
-
disabled: boolean;
|
|
13
|
-
inputRef: React.RefObject<TextInput>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const TimeInput: React.FC<TimeInputProps> = ({
|
|
17
|
-
type,
|
|
18
|
-
value,
|
|
19
|
-
onChangeText,
|
|
20
|
-
onFocus,
|
|
21
|
-
onBlur,
|
|
22
|
-
isActive,
|
|
23
|
-
disabled,
|
|
24
|
-
inputRef,
|
|
25
|
-
}) => {
|
|
26
|
-
const maxLength = type === 'hour' ? 2 : 2;
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<TextInput
|
|
30
|
-
ref={inputRef}
|
|
31
|
-
value={value}
|
|
32
|
-
onChangeText={onChangeText}
|
|
33
|
-
onFocus={onFocus}
|
|
34
|
-
onBlur={onBlur}
|
|
35
|
-
keyboardType="numeric"
|
|
36
|
-
maxLength={maxLength}
|
|
37
|
-
selectTextOnFocus
|
|
38
|
-
editable={!disabled}
|
|
39
|
-
style={[
|
|
40
|
-
timePickerStyles.timeInput,
|
|
41
|
-
isActive && timePickerStyles.activeInput,
|
|
42
|
-
{
|
|
43
|
-
fontSize: 16,
|
|
44
|
-
fontWeight: '600',
|
|
45
|
-
color: isActive ? '#3b82f6' : '#111827',
|
|
46
|
-
textAlign: 'center',
|
|
47
|
-
paddingHorizontal: 2,
|
|
48
|
-
paddingVertical: 2,
|
|
49
|
-
}
|
|
50
|
-
]}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Input } from '@idealyst/components';
|
|
3
|
-
import { timePickerStyles } from '../TimePicker.styles';
|
|
4
|
-
|
|
5
|
-
interface TimeInputProps {
|
|
6
|
-
type: 'hour' | 'minute';
|
|
7
|
-
value: string;
|
|
8
|
-
onChangeText: (value: string) => void;
|
|
9
|
-
onFocus: () => void;
|
|
10
|
-
onBlur: () => void;
|
|
11
|
-
isActive: boolean;
|
|
12
|
-
disabled: boolean;
|
|
13
|
-
inputRef: React.RefObject<HTMLInputElement>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const TimeInput: React.FC<TimeInputProps> = ({
|
|
17
|
-
type,
|
|
18
|
-
value,
|
|
19
|
-
onChangeText,
|
|
20
|
-
onFocus,
|
|
21
|
-
onBlur,
|
|
22
|
-
isActive,
|
|
23
|
-
disabled,
|
|
24
|
-
inputRef,
|
|
25
|
-
}) => {
|
|
26
|
-
const handleChange = (inputValue: string) => {
|
|
27
|
-
onChangeText(inputValue);
|
|
28
|
-
|
|
29
|
-
// Smart focus switching for web
|
|
30
|
-
if (type === 'hour') {
|
|
31
|
-
const num = parseInt(inputValue);
|
|
32
|
-
if (!isNaN(num) && num >= 2) {
|
|
33
|
-
// Wait a moment then focus minutes
|
|
34
|
-
setTimeout(() => {
|
|
35
|
-
const minuteInput = document.querySelector('input[data-time-input="minute"]') as HTMLInputElement;
|
|
36
|
-
minuteInput?.focus();
|
|
37
|
-
}, 100);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const handleFocus = () => {
|
|
43
|
-
onFocus();
|
|
44
|
-
// For web, sync the displayed value on focus
|
|
45
|
-
if (type === 'minute' && value.length === 1) {
|
|
46
|
-
onChangeText(value.padStart(2, '0'));
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<Input
|
|
52
|
-
ref={inputRef}
|
|
53
|
-
variant="bare"
|
|
54
|
-
value={value}
|
|
55
|
-
onChangeText={handleChange}
|
|
56
|
-
onFocus={handleFocus}
|
|
57
|
-
onBlur={onBlur}
|
|
58
|
-
style={[
|
|
59
|
-
timePickerStyles.timeInput,
|
|
60
|
-
isActive ? timePickerStyles.activeInput : {}
|
|
61
|
-
]}
|
|
62
|
-
disabled={disabled}
|
|
63
|
-
data-time-input={type}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import { ViewStyle } from 'react-native';
|
|
3
|
-
|
|
4
|
-
export interface DateTimePickerProps {
|
|
5
|
-
/** Current selected date and time */
|
|
6
|
-
value?: Date;
|
|
7
|
-
|
|
8
|
-
/** Called when date/time 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 HH:mm') */
|
|
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
|
-
/** Time picker mode */
|
|
45
|
-
timeMode?: '12h' | '24h';
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
/** Time step in minutes */
|
|
49
|
-
timeStep?: number;
|
|
50
|
-
|
|
51
|
-
/** Custom styles */
|
|
52
|
-
style?: ViewStyle;
|
|
53
|
-
|
|
54
|
-
/** Test ID for testing */
|
|
55
|
-
testID?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface TimePickerProps {
|
|
59
|
-
/** Current selected time */
|
|
60
|
-
value?: Date;
|
|
61
|
-
|
|
62
|
-
/** Called when time is selected */
|
|
63
|
-
onChange: (time: Date) => void;
|
|
64
|
-
|
|
65
|
-
/** Disabled state */
|
|
66
|
-
disabled?: boolean;
|
|
67
|
-
|
|
68
|
-
/** Time picker mode */
|
|
69
|
-
mode?: '12h' | '24h';
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/** Time step in minutes */
|
|
73
|
-
step?: number;
|
|
74
|
-
|
|
75
|
-
/** Custom styles */
|
|
76
|
-
style?: ViewStyle;
|
|
77
|
-
|
|
78
|
-
/** Test ID for testing */
|
|
79
|
-
testID?: string;
|
|
80
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Dimensions } from 'react-native';
|
|
2
|
-
|
|
3
|
-
export const getDimensions = () => Dimensions.get('window');
|
|
4
|
-
|
|
5
|
-
export const addEventListener = (callback: (data: { window: { width: number; height: number } }) => void) => {
|
|
6
|
-
return Dimensions.addEventListener('change', ({ window }) => {
|
|
7
|
-
callback({ window });
|
|
8
|
-
});
|
|
9
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Dimensions } from 'react-native';
|
|
2
|
-
|
|
3
|
-
export const getDimensions = () => Dimensions.get('window');
|
|
4
|
-
|
|
5
|
-
export const addEventListener = (callback: (data: { window: { width: number; height: number } }) => void) => {
|
|
6
|
-
return Dimensions.addEventListener('change', ({ window }) => {
|
|
7
|
-
callback({ window });
|
|
8
|
-
});
|
|
9
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export const getDimensions = () => {
|
|
2
|
-
if (typeof window !== 'undefined') {
|
|
3
|
-
return {
|
|
4
|
-
width: window.innerWidth,
|
|
5
|
-
height: window.innerHeight,
|
|
6
|
-
};
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
return { width: 1024, height: 768 }; // Default desktop size
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const addEventListener = (callback: (data: { window: { width: number; height: number } }) => void) => {
|
|
13
|
-
if (typeof window !== 'undefined') {
|
|
14
|
-
const handleResize = () => {
|
|
15
|
-
callback({
|
|
16
|
-
window: {
|
|
17
|
-
width: window.innerWidth,
|
|
18
|
-
height: window.innerHeight,
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
window.addEventListener('resize', handleResize);
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
remove: () => window.removeEventListener('resize', handleResize),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
remove: () => {},
|
|
32
|
-
};
|
|
33
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { DateTimeRangePickerProps } from './types';
|
|
3
|
-
import { DateTimeRangePickerBase } from './DateTimeRangePickerBase';
|
|
4
|
-
import { RangeCalendar } from '../DateRangePicker/RangeCalendar.native';
|
|
5
|
-
import { TimePicker } from '../DateTimePicker/TimePicker.native';
|
|
6
|
-
import { dateTimeRangePickerStyles } from './DateTimeRangePicker.styles';
|
|
7
|
-
|
|
8
|
-
const DateTimeRangePicker: React.FC<DateTimeRangePickerProps> = (props) => {
|
|
9
|
-
dateTimeRangePickerStyles.useVariants({});
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<DateTimeRangePickerBase
|
|
13
|
-
{...props}
|
|
14
|
-
renderRangeCalendar={(rangeCalendarProps) => (
|
|
15
|
-
<RangeCalendar {...rangeCalendarProps} />
|
|
16
|
-
)}
|
|
17
|
-
renderTimePicker={(timePickerProps) => (
|
|
18
|
-
<TimePicker {...timePickerProps} />
|
|
19
|
-
)}
|
|
20
|
-
/>
|
|
21
|
-
);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default DateTimeRangePicker;
|