Date input improvements (#7639)

* add max date, use modern field for birthday input

* rm legacy date input

* handle simplifying to simpleDateString internally

* update jsdoc
This commit is contained in:
Samuel Newman
2025-02-03 12:27:58 -08:00
committed by GitHub
parent 25991af722
commit 23e62b18de
9 changed files with 37 additions and 203 deletions
-105
View File
@@ -1,105 +0,0 @@
import {useCallback, useState} from 'react'
import {StyleProp, StyleSheet, TextStyle, View, ViewStyle} from 'react-native'
import DatePicker from 'react-native-date-picker'
import {
FontAwesomeIcon,
FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {useLingui} from '@lingui/react'
import {usePalette} from '#/lib/hooks/usePalette'
import {TypographyVariant} from '#/lib/ThemeContext'
import {useTheme} from '#/lib/ThemeContext'
import {isAndroid, isIOS} from '#/platform/detection'
import {Text} from '../text/Text'
import {Button, ButtonType} from './Button'
interface Props {
testID?: string
value: Date
onChange: (date: Date) => void
buttonType?: ButtonType
buttonStyle?: StyleProp<ViewStyle>
buttonLabelType?: TypographyVariant
buttonLabelStyle?: StyleProp<TextStyle>
accessibilityLabel: string
accessibilityHint: string
accessibilityLabelledBy?: string
handleAsUTC?: boolean
}
export function DateInput(props: Props) {
const {i18n} = useLingui()
const [show, setShow] = useState(false)
const theme = useTheme()
const pal = usePalette('default')
const onChangeInternal = useCallback(
(date: Date) => {
setShow(false)
props.onChange(date)
},
[setShow, props],
)
const onPress = useCallback(() => {
setShow(true)
}, [setShow])
const onCancel = useCallback(() => {
setShow(false)
}, [])
return (
<View>
{isAndroid && (
<Button
type={props.buttonType}
style={props.buttonStyle}
onPress={onPress}
accessibilityLabel={props.accessibilityLabel}
accessibilityHint={props.accessibilityHint}
accessibilityLabelledBy={props.accessibilityLabelledBy}>
<View style={styles.button}>
<FontAwesomeIcon
icon={['far', 'calendar']}
style={pal.textLight as FontAwesomeIconStyle}
/>
<Text
type={props.buttonLabelType}
style={[pal.text, props.buttonLabelStyle]}>
{i18n.date(props.value, {
timeZone: props.handleAsUTC ? 'UTC' : undefined,
})}
</Text>
</View>
</Button>
)}
{(isIOS || show) && (
<DatePicker
timeZoneOffsetInMinutes={0}
modal={isAndroid}
open={isAndroid}
theme={theme.colorScheme}
date={props.value}
onDateChange={onChangeInternal}
onConfirm={onChangeInternal}
onCancel={onCancel}
mode="date"
testID={props.testID ? `${props.testID}-datepicker` : undefined}
accessibilityLabel={props.accessibilityLabel}
accessibilityHint={props.accessibilityHint}
accessibilityLabelledBy={props.accessibilityLabelledBy}
/>
)}
</View>
)
}
const styles = StyleSheet.create({
button: {
flexDirection: 'row',
alignItems: 'center',
gap: 10,
},
})
-76
View File
@@ -1,76 +0,0 @@
import {useCallback, useState} from 'react'
import {StyleProp, StyleSheet, TextStyle, View, ViewStyle} from 'react-native'
// @ts-ignore types not available -prf
import {unstable_createElement} from 'react-native-web'
import {usePalette} from '#/lib/hooks/usePalette'
interface Props {
testID?: string
value: Date
onChange: (date: Date) => void
buttonType?: string
buttonStyle?: StyleProp<ViewStyle>
buttonLabelType?: string
buttonLabelStyle?: StyleProp<TextStyle>
accessibilityLabel: string
accessibilityHint: string
accessibilityLabelledBy?: string
}
export function DateInput(props: Props) {
const pal = usePalette('default')
const [value, setValue] = useState(toDateInputValue(props.value))
const onChangeInternal = useCallback(
(v: Date) => {
if (!v) {
return
}
setValue(toDateInputValue(v))
props.onChange(v)
},
[setValue, props],
)
return (
<View style={[pal.borderDark, styles.container]}>
{unstable_createElement('input', {
type: 'date',
testID: props.testID,
value,
onChange: (e: any) => onChangeInternal(e.currentTarget.valueAsDate),
style: [pal.text, pal.view, pal.border, styles.textInput],
placeholderTextColor: pal.colors.textLight,
accessibilityLabel: props.accessibilityLabel,
accessibilityHint: props.accessibilityHint,
accessibilityLabelledBy: props.accessibilityLabelledBy,
})}
</View>
)
}
// we need the date in the form yyyy-MM-dd to pass to the input
function toDateInputValue(d: Date): string {
return d.toISOString().split('T')[0]
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
paddingHorizontal: 4,
borderWidth: 1,
borderRadius: 10,
},
textInput: {
flex: 1,
width: '100%',
paddingVertical: 10,
paddingHorizontal: 10,
fontSize: 17,
letterSpacing: 0.25,
fontWeight: '400',
borderRadius: 10,
borderWidth: 0,
},
})