Bluesky app fork with some witchin' additions 馃挮
at readme-update 117 lines 3.4 kB view raw
1import {useCallback, useImperativeHandle} from 'react' 2import {Keyboard, View} from 'react-native' 3import DatePicker from 'react-native-date-picker' 4import {msg, Trans} from '@lingui/macro' 5import {useLingui} from '@lingui/react' 6 7import {atoms as a, useTheme} from '#/alf' 8import {Button, ButtonText} from '#/components/Button' 9import * as Dialog from '#/components/Dialog' 10import {type DateFieldProps} from '#/components/forms/DateField/types' 11import {toSimpleDateString} from '#/components/forms/DateField/utils' 12import * as TextField from '#/components/forms/TextField' 13import {DateFieldButton} from './index.shared' 14 15export * as utils from '#/components/forms/DateField/utils' 16export const LabelText = TextField.LabelText 17 18/** 19 * Date-only input. Accepts a string in the format YYYY-MM-DD, or a Date object. 20 * Date objects are converted to strings in the format YYYY-MM-DD. 21 * Returns a string in the format YYYY-MM-DD. 22 * 23 * To generate a string in the format YYYY-MM-DD from a Date object, use the 24 * `utils.toSimpleDateString(Date)` export of this file. 25 */ 26export function DateField({ 27 value, 28 inputRef, 29 onChangeDate, 30 testID, 31 label, 32 isInvalid, 33 accessibilityHint, 34 maximumDate, 35}: DateFieldProps) { 36 const {_, i18n} = useLingui() 37 const t = useTheme() 38 const control = Dialog.useDialogControl() 39 40 const onChangeInternal = useCallback( 41 (date: Date | undefined) => { 42 if (date) { 43 const formatted = toSimpleDateString(date) 44 onChangeDate(formatted) 45 } 46 }, 47 [onChangeDate], 48 ) 49 50 useImperativeHandle( 51 inputRef, 52 () => ({ 53 focus: () => { 54 Keyboard.dismiss() 55 control.open() 56 }, 57 blur: () => { 58 control.close() 59 }, 60 }), 61 [control], 62 ) 63 64 return ( 65 <> 66 <DateFieldButton 67 label={label} 68 value={value} 69 onPress={() => { 70 Keyboard.dismiss() 71 control.open() 72 }} 73 isInvalid={isInvalid} 74 accessibilityHint={accessibilityHint} 75 /> 76 <Dialog.Outer 77 control={control} 78 testID={testID} 79 nativeOptions={{preventExpansion: true}}> 80 <Dialog.Handle /> 81 <Dialog.ScrollableInner label={label}> 82 <View style={a.gap_lg}> 83 <View style={[a.relative, a.w_full, a.align_center]}> 84 <DatePicker 85 timeZoneOffsetInMinutes={0} 86 theme={t.scheme} 87 date={new Date(toSimpleDateString(value))} 88 onDateChange={onChangeInternal} 89 mode="date" 90 locale={i18n.locale} 91 testID={`${testID}-datepicker`} 92 aria-label={label} 93 accessibilityLabel={label} 94 accessibilityHint={accessibilityHint} 95 maximumDate={ 96 maximumDate 97 ? new Date(toSimpleDateString(maximumDate)) 98 : undefined 99 } 100 /> 101 </View> 102 <Button 103 label={_(msg`Done`)} 104 onPress={() => control.close()} 105 size="large" 106 color="primary" 107 variant="solid"> 108 <ButtonText> 109 <Trans>Done</Trans> 110 </ButtonText> 111 </Button> 112 </View> 113 </Dialog.ScrollableInner> 114 </Dialog.Outer> 115 </> 116 ) 117}