Skip to content

Commit 31184da

Browse files
Fixed am/pm switch + onConfirm
1 parent 2cc1ff3 commit 31184da

File tree

11 files changed

+244
-60
lines changed

11 files changed

+244
-60
lines changed

example/src/App.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ import {
1010
DarkTheme,
1111
useTheme,
1212
} from 'react-native-paper';
13-
import { DatePickerModal } from '../../src';
13+
import { DatePickerModal, TimePickerModal } from '../../src';
1414
import { Platform } from 'react-native';
1515

16-
import TimePickerModal from '../../src/Time/TimePickerModal';
1716
import DatePickerInput from '../../src/Date/DatePickerInput';
1817
import DateRangeInput from '../../src/Date/DateRangeInput';
1918

@@ -118,7 +117,14 @@ function App({
118117
label={'Select date'} // optional
119118
/>
120119

121-
<TimePickerModal visible={timeOpen} onDismiss={onDismissTime} />
120+
<TimePickerModal
121+
visible={timeOpen}
122+
onDismiss={onDismissTime}
123+
onConfirm={({ hours, minutes }) => {
124+
setTimeOpen(false);
125+
console.log({ hours, minutes });
126+
}}
127+
/>
122128
</View>
123129
</ScrollView>
124130
);
@@ -131,7 +137,13 @@ export default function AppWithProviders() {
131137
};
132138

133139
return (
134-
<PaperProvider theme={dark ? DarkTheme : DefaultTheme}>
140+
<PaperProvider
141+
theme={
142+
dark
143+
? { ...DarkTheme, roundness: 10 }
144+
: { ...DefaultTheme, roundness: 10 }
145+
}
146+
>
135147
<React.Fragment>
136148
{Platform.OS === 'web' ? (
137149
<style type="text/css">{`

src/Date/DateRangeInput.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ export default function DateRangeInput() {
2929
/>
3030
<Text>Van</Text>
3131
</View>
32-
<Text style={{ fontSize: 24, marginLeft: 6, marginRight: 6 }}>-</Text>
32+
<View>
33+
<Text style={{ fontSize: 16, marginLeft: 12, marginRight: 12 }}>
34+
to
35+
</Text>
36+
<Text style={{ opacity: 0 }} accessible={false}>
37+
tot
38+
</Text>
39+
</View>
3340
<View style={{ flex: 1 }}>
3441
<TextInputWithMask
3542
value={''}

src/Date/Swiper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ function Swiper({
167167
initialScrollIndex={startAtIndex}
168168
keyExtractor={keyExtractor}
169169
getItemLayout={getItemLayout}
170-
windowSize={3}
170+
windowSize={scrollMode === 'horizontal' ? 1 : 3}
171171
getItem={getItem}
172172
renderItem={renderPage}
173173
style={styles.viewPager}

src/Time/AmPmSwitcher.tsx

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,119 @@
11
import * as React from 'react'
22
import { View, StyleSheet } from 'react-native'
33
import { Text, TouchableRipple, useTheme } from 'react-native-paper'
4+
import { useMemo } from 'react'
5+
import Color from 'color'
6+
import {
7+
getHourType,
8+
hourTypes,
9+
useInputColors,
10+
useSwitchColors,
11+
} from './timeUtils'
412

5-
export default function AmPmSwitcher() {
13+
export default function AmPmSwitcher({
14+
hours,
15+
onChange,
16+
}: {
17+
hours: number
18+
onChange: (hours: number) => any
19+
}) {
620
const theme = useTheme()
21+
const backgroundColor = useMemo<string>(() => {
22+
if (theme.dark) {
23+
return Color(theme.colors.surface).lighten(1.2).hex()
24+
}
25+
return Color(theme.colors.surface).darken(0.1).hex()
26+
}, [theme])
27+
28+
const hourType = getHourType(hours)
29+
const isAM = hourType === hourTypes.am
30+
const isPM = hourType === hourTypes.pm
31+
732
return (
833
<View
934
style={[
1035
styles.root,
1136
{
12-
borderColor: theme.colors.backdrop,
37+
borderColor: backgroundColor,
1338
borderRadius: theme.roundness,
1439
},
1540
]}
1641
>
17-
<SwitchButton label="AM" onPress={() => {}} />
18-
<View
19-
style={[
20-
styles.switchSeparator,
21-
{ backgroundColor: theme.colors.backdrop },
22-
]}
42+
<SwitchButton
43+
label="AM"
44+
onPress={isAM ? undefined : () => onChange(hours - 12)}
45+
selected={isAM}
46+
disabled={isAM}
47+
/>
48+
<View style={[styles.switchSeparator, { backgroundColor }]} />
49+
<SwitchButton
50+
label="PM"
51+
onPress={isPM ? undefined : () => onChange(hours + 12)}
52+
selected={isPM}
53+
disabled={isPM}
2354
/>
24-
<SwitchButton label="PM" onPress={() => {}} />
2555
</View>
2656
)
2757
}
2858

2959
function SwitchButton({
3060
label,
3161
onPress,
62+
selected,
63+
disabled,
3264
}: {
3365
label: string
34-
onPress: () => any
66+
onPress: (() => any) | undefined
67+
selected: boolean
68+
disabled: boolean
3569
}) {
3670
const theme = useTheme()
71+
const { backgroundColor, color } = useSwitchColors(selected)
72+
console.log({ backgroundColor, color })
3773
return (
38-
<TouchableRipple onPress={onPress} style={styles.switchButton}>
39-
<Text selectable={false} style={{ ...theme.fonts.medium }}>
40-
{label}
41-
</Text>
74+
<TouchableRipple
75+
onPress={onPress}
76+
style={styles.switchButton}
77+
accessibilityLabel={label}
78+
accessibilityTraits={disabled ? ['button', 'disabled'] : 'button'}
79+
accessibilityComponentType="button"
80+
accessibilityRole="button"
81+
accessibilityState={{ disabled }}
82+
disabled={disabled}
83+
>
84+
<View style={[styles.switchButtonInner, { backgroundColor }]}>
85+
<Text
86+
selectable={false}
87+
style={[
88+
{
89+
...theme.fonts.medium,
90+
color: color,
91+
},
92+
]}
93+
>
94+
{label}
95+
</Text>
96+
</View>
4297
</TouchableRipple>
4398
)
4499
}
45100

46101
const styles = StyleSheet.create({
47102
root: {
48103
width: 50,
49-
height: 96,
104+
height: 80,
50105
borderWidth: 1,
106+
overflow: 'hidden',
51107
},
52108
switchSeparator: {
53109
height: 1,
54-
width: 41,
110+
width: 48,
55111
},
56112
switchButton: {
57113
flex: 1,
114+
},
115+
switchButtonInner: {
116+
flex: 1,
58117
alignItems: 'center',
59118
justifyContent: 'center',
60119
},

src/Time/AnalogClock.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
clockTypes,
1212
getAngle,
1313
getHours,
14+
getHourType,
15+
getHourTypeFromOffset,
1416
getMinutes,
15-
isPM,
17+
hourTypes,
1618
PossibleClockTypes,
1719
} from './timeUtils'
1820
import * as React from 'react'
@@ -23,6 +25,7 @@ import AnalogClockHours from './AnalogClockHours'
2325
import AnimatedClockSwitcher from './AnimatedClockSwitcher'
2426
import AnalogClockMinutes from './AnalogClockMinutes'
2527

28+
// 250? when bigger?
2629
export const circleSize = 215
2730

2831
function AnalogClock({
@@ -48,11 +51,14 @@ function AnalogClock({
4851
}) {
4952
const theme = useTheme()
5053

54+
// used to make pointer shorter if hours are selected and above 12
55+
const shortPointer = hours > 12 && is24Hour
56+
5157
const clockRef = React.useRef<View | null>(null)
5258
const elementX = React.useRef<number>(0)
5359
const elementY = React.useRef<number>(0)
5460

55-
// Hooks are nice, sometimes :-)..
61+
// Hooks are nice, sometimes... :-)..
5662
// We need the latest values, since the onPointerMove uses a closure to the function
5763
const hoursRef = useLatest(hours)
5864
const onChangeRef = useLatest(onChange)
@@ -67,8 +73,15 @@ function AnalogClock({
6773

6874
let angle = getAngle(x, y, circleSize)
6975
if (focusedRef.current === clockTypes.hours) {
70-
let pickedHours = getHours(angle)
71-
if (is24HourRef.current && isPM(x, y, circleSize)) {
76+
let previousHourType = getHourType(hoursRef.current)
77+
let pickedHours = getHours(angle, previousHourType)
78+
79+
// TODO: check which mode is switched on am/pm
80+
if (
81+
(is24HourRef.current &&
82+
getHourTypeFromOffset(x, y, circleSize) === hourTypes.pm) ||
83+
(!is24HourRef.current && previousHourType === hourTypes.pm)
84+
) {
7285
pickedHours += 12
7386
}
7487
if (hoursRef.current !== pickedHours || final) {
@@ -120,8 +133,7 @@ function AnalogClock({
120133
[elementX, elementY]
121134
)
122135

123-
// used to make pointer shorter if hours are selected and above 12
124-
const dynamicSize = focused === clockTypes.hours && hours > 12 ? 33 : 0
136+
const dynamicSize = focused === clockTypes.hours && shortPointer ? 33 : 0
125137
const pointerNumber = focused === clockTypes.hours ? hours : minutes
126138
const degreesPerNumber = focused === clockTypes.hours ? 30 : 6
127139
return (

src/Time/TimeInput.tsx

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ import { View, TextInput, TextInputProps, StyleSheet } from 'react-native'
33
import { useTheme, TouchableRipple } from 'react-native-paper'
44

55
import Color from 'color'
6-
import { inputTypes, PossibleClockTypes, PossibleInputTypes } from './timeUtils'
7-
import { useMemo } from 'react'
6+
import {
7+
inputTypes,
8+
PossibleClockTypes,
9+
PossibleInputTypes,
10+
useInputColors,
11+
} from './timeUtils'
812

913
interface TimeInputProps
1014
extends Omit<Omit<TextInputProps, 'value'>, 'onFocus'> {
1115
value: number
1216
clockType: PossibleClockTypes
1317
onPress?: (type: PossibleClockTypes) => any
14-
pressed?: boolean
18+
pressed: boolean
1519
onChanged: (n: number) => any
1620
inputType: PossibleInputTypes
1721
}
@@ -47,26 +51,8 @@ function TimeInput(
4751
const [inputFocused, setInputFocused] = React.useState<boolean>(false)
4852

4953
const highlighted = inputType === inputTypes.picker ? pressed : inputFocused
50-
const backgroundColor = useMemo<string>(() => {
51-
if (theme.dark) {
52-
if (highlighted) {
53-
return Color(theme.colors.primary).hex()
54-
}
55-
return Color(theme.colors.surface).lighten(1.2).hex()
56-
}
57-
58-
if (highlighted) {
59-
return Color(theme.colors.primary).lighten(1).hex()
60-
}
61-
return Color(theme.colors.surface).darken(0.1).hex()
62-
}, [highlighted, theme])
6354

64-
const color = useMemo<string>(() => {
65-
if (highlighted && !theme.dark) {
66-
return theme.colors.primary
67-
}
68-
return theme.colors.text
69-
}, [highlighted, theme])
55+
const { color, backgroundColor } = useInputColors(highlighted)
7056

7157
let formattedValue = controlledValue
7258
if (!inputFocused) {

src/Time/TimeInputs.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import TimeInput from './TimeInput'
2020
import AmPmSwitcher from './AmPmSwitcher'
2121
import AnalogClock, { circleSize } from './AnalogClock'
22+
import { useLatest } from '../utils'
2223

2324
function TimeInputs({
2425
hours,
@@ -61,6 +62,18 @@ function TimeInputs({
6162
// TODO: close modal and persist time
6263
}, [])
6364

65+
const minutesRef = useLatest(minutes)
66+
const onChangeHours = React.useCallback(
67+
(newHours: number) => {
68+
onChange({
69+
hours: newHours,
70+
minutes: minutesRef.current,
71+
focused: clockTypes.hours,
72+
})
73+
},
74+
[onChange, minutesRef]
75+
)
76+
6477
return (
6578
<View
6679
style={[
@@ -113,7 +126,7 @@ function TimeInputs({
113126
{!is24Hour && (
114127
<>
115128
<View style={styles.spaceBetweenInputsAndSwitcher} />
116-
<AmPmSwitcher />
129+
<AmPmSwitcher hours={hours} onChange={onChangeHours} />
117130
</>
118131
)}
119132
</View>

src/Time/TimePicker.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ function TimePicker({
4141
})
4242
const formatted = formatter.format(new Date(Date.UTC(2020, 1, 1, 23)))
4343
return formatted.includes('23')
44+
// return false
4445
}, [])
4546

4647
return (

src/Time/TimePickerModal.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ const supportedOrientations: any[] = [
3232
export function TimePickerModal({
3333
visible,
3434
onDismiss,
35+
onConfirm,
3536
}: {
3637
visible: boolean
3738
onDismiss: () => any
39+
onConfirm: ({ hours, minutes }: { hours: number; minutes: number }) => any
3840
}) {
3941
const theme = useTheme()
4042
let date = new Date()
@@ -80,7 +82,7 @@ export function TimePickerModal({
8082
<>
8183
<KeyboardAvoidingView
8284
style={styles.keyboardView}
83-
behavior={Platform.OS == 'ios' ? 'padding' : 'height'}
85+
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
8486
>
8587
<TouchableWithoutFeedback onPress={onDismiss}>
8688
<View
@@ -130,7 +132,9 @@ export function TimePickerModal({
130132
/>
131133
<View style={styles.fill} />
132134
<Button onPress={onDismiss}>Cancel</Button>
133-
<Button onPress={() => {}}>Ok</Button>
135+
<Button onPress={() => onConfirm({ hours, minutes })}>
136+
Ok
137+
</Button>
134138
</View>
135139
</Animated.View>
136140
</View>

0 commit comments

Comments
 (0)