connect inputs together in signup (#7809)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react'
|
import {useCallback, useImperativeHandle, useState} from 'react'
|
||||||
|
import {Keyboard} from 'react-native'
|
||||||
import DatePicker from 'react-native-date-picker'
|
import DatePicker from 'react-native-date-picker'
|
||||||
|
|
||||||
import {useTheme} from '#/alf'
|
import {useTheme} from '#/alf'
|
||||||
@@ -12,6 +13,7 @@ export const LabelText = TextField.LabelText
|
|||||||
|
|
||||||
export function DateField({
|
export function DateField({
|
||||||
value,
|
value,
|
||||||
|
inputRef,
|
||||||
onChangeDate,
|
onChangeDate,
|
||||||
label,
|
label,
|
||||||
isInvalid,
|
isInvalid,
|
||||||
@@ -20,9 +22,9 @@ export function DateField({
|
|||||||
maximumDate,
|
maximumDate,
|
||||||
}: DateFieldProps) {
|
}: DateFieldProps) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const [open, setOpen] = React.useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
const onChangeInternal = React.useCallback(
|
const onChangeInternal = useCallback(
|
||||||
(date: Date) => {
|
(date: Date) => {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
|
|
||||||
@@ -32,11 +34,25 @@ export function DateField({
|
|||||||
[onChangeDate, setOpen],
|
[onChangeDate, setOpen],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onPress = React.useCallback(() => {
|
useImperativeHandle(
|
||||||
|
inputRef,
|
||||||
|
() => ({
|
||||||
|
focus: () => {
|
||||||
|
Keyboard.dismiss()
|
||||||
|
setOpen(true)
|
||||||
|
},
|
||||||
|
blur: () => {
|
||||||
|
setOpen(false)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
||||||
|
const onPress = useCallback(() => {
|
||||||
setOpen(true)
|
setOpen(true)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const onCancel = React.useCallback(() => {
|
const onCancel = useCallback(() => {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import {useCallback, useImperativeHandle} from 'react'
|
||||||
import {Keyboard, View} from 'react-native'
|
import {Keyboard, View} from 'react-native'
|
||||||
import DatePicker from 'react-native-date-picker'
|
import DatePicker from 'react-native-date-picker'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
@@ -25,6 +25,7 @@ export const LabelText = TextField.LabelText
|
|||||||
*/
|
*/
|
||||||
export function DateField({
|
export function DateField({
|
||||||
value,
|
value,
|
||||||
|
inputRef,
|
||||||
onChangeDate,
|
onChangeDate,
|
||||||
testID,
|
testID,
|
||||||
label,
|
label,
|
||||||
@@ -36,7 +37,7 @@ export function DateField({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
|
|
||||||
const onChangeInternal = React.useCallback(
|
const onChangeInternal = useCallback(
|
||||||
(date: Date | undefined) => {
|
(date: Date | undefined) => {
|
||||||
if (date) {
|
if (date) {
|
||||||
const formatted = toSimpleDateString(date)
|
const formatted = toSimpleDateString(date)
|
||||||
@@ -46,6 +47,20 @@ export function DateField({
|
|||||||
[onChangeDate],
|
[onChangeDate],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
useImperativeHandle(
|
||||||
|
inputRef,
|
||||||
|
() => ({
|
||||||
|
focus: () => {
|
||||||
|
Keyboard.dismiss()
|
||||||
|
control.open()
|
||||||
|
},
|
||||||
|
blur: () => {
|
||||||
|
control.close()
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[control],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DateFieldButton
|
<DateFieldButton
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ const Input = TextField.createInput(InputBase as unknown as typeof TextInput)
|
|||||||
|
|
||||||
export function DateField({
|
export function DateField({
|
||||||
value,
|
value,
|
||||||
|
inputRef,
|
||||||
onChangeDate,
|
onChangeDate,
|
||||||
label,
|
label,
|
||||||
isInvalid,
|
isInvalid,
|
||||||
@@ -58,9 +59,9 @@ export function DateField({
|
|||||||
<TextField.Icon icon={CalendarDays} />
|
<TextField.Icon icon={CalendarDays} />
|
||||||
<Input
|
<Input
|
||||||
value={toSimpleDateString(value)}
|
value={toSimpleDateString(value)}
|
||||||
|
inputRef={inputRef as React.Ref<TextInput>}
|
||||||
label={label}
|
label={label}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
onChangeText={() => {}}
|
|
||||||
testID={testID}
|
testID={testID}
|
||||||
accessibilityHint={accessibilityHint}
|
accessibilityHint={accessibilityHint}
|
||||||
// @ts-expect-error not typed as <input type="date"> even though it is one
|
// @ts-expect-error not typed as <input type="date"> even though it is one
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
|
export type DateFieldRef = {
|
||||||
|
focus: () => void
|
||||||
|
blur: () => void
|
||||||
|
}
|
||||||
export type DateFieldProps = {
|
export type DateFieldProps = {
|
||||||
value: string | Date
|
value: string | Date
|
||||||
onChangeDate: (date: string) => void
|
onChangeDate: (date: string) => void
|
||||||
label: string
|
label: string
|
||||||
|
inputRef?: React.Ref<DateFieldRef>
|
||||||
isInvalid?: boolean
|
isInvalid?: boolean
|
||||||
testID?: string
|
testID?: string
|
||||||
accessibilityHint?: string
|
accessibilityHint?: string
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, {useRef} from 'react'
|
import React, {useRef} from 'react'
|
||||||
import {View} from 'react-native'
|
import {TextInput, View} from 'react-native'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import * as EmailValidator from 'email-validator'
|
import * as EmailValidator from 'email-validator'
|
||||||
@@ -11,8 +11,9 @@ import {logger} from '#/logger'
|
|||||||
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
|
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
|
||||||
import {is13, is18, useSignupContext} from '#/screens/Signup/state'
|
import {is13, is18, useSignupContext} from '#/screens/Signup/state'
|
||||||
import {Policies} from '#/screens/Signup/StepInfo/Policies'
|
import {Policies} from '#/screens/Signup/StepInfo/Policies'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a, native} from '#/alf'
|
||||||
import * as DateField from '#/components/forms/DateField'
|
import * as DateField from '#/components/forms/DateField'
|
||||||
|
import {DateFieldRef} from '#/components/forms/DateField/types'
|
||||||
import {FormError} from '#/components/forms/FormError'
|
import {FormError} from '#/components/forms/FormError'
|
||||||
import {HostingProvider} from '#/components/forms/HostingProvider'
|
import {HostingProvider} from '#/components/forms/HostingProvider'
|
||||||
import * as TextField from '#/components/forms/TextField'
|
import * as TextField from '#/components/forms/TextField'
|
||||||
@@ -51,6 +52,10 @@ export function StepInfo({
|
|||||||
const prevEmailValueRef = useRef<string>(state.email)
|
const prevEmailValueRef = useRef<string>(state.email)
|
||||||
const passwordValueRef = useRef<string>(state.password)
|
const passwordValueRef = useRef<string>(state.password)
|
||||||
|
|
||||||
|
const emailInputRef = useRef<TextInput>(null)
|
||||||
|
const passwordInputRef = useRef<TextInput>(null)
|
||||||
|
const birthdateInputRef = useRef<DateFieldRef>(null)
|
||||||
|
|
||||||
const [hasWarnedEmail, setHasWarnedEmail] = React.useState<boolean>(false)
|
const [hasWarnedEmail, setHasWarnedEmail] = React.useState<boolean>(false)
|
||||||
|
|
||||||
const tldtsRef = React.useRef<typeof tldts>()
|
const tldtsRef = React.useRef<typeof tldts>()
|
||||||
@@ -155,6 +160,11 @@ export function StepInfo({
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
keyboardType="email-address"
|
keyboardType="email-address"
|
||||||
|
returnKeyType="next"
|
||||||
|
submitBehavior={native('submit')}
|
||||||
|
onSubmitEditing={native(() =>
|
||||||
|
emailInputRef.current?.focus(),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
</View>
|
</View>
|
||||||
@@ -167,6 +177,7 @@ export function StepInfo({
|
|||||||
<TextField.Icon icon={Envelope} />
|
<TextField.Icon icon={Envelope} />
|
||||||
<TextField.Input
|
<TextField.Input
|
||||||
testID="emailInput"
|
testID="emailInput"
|
||||||
|
inputRef={emailInputRef}
|
||||||
onChangeText={value => {
|
onChangeText={value => {
|
||||||
emailValueRef.current = value.trim()
|
emailValueRef.current = value.trim()
|
||||||
if (hasWarnedEmail) {
|
if (hasWarnedEmail) {
|
||||||
@@ -178,6 +189,11 @@ export function StepInfo({
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
keyboardType="email-address"
|
keyboardType="email-address"
|
||||||
|
returnKeyType="next"
|
||||||
|
submitBehavior={native('submit')}
|
||||||
|
onSubmitEditing={native(() =>
|
||||||
|
passwordInputRef.current?.focus(),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
</View>
|
</View>
|
||||||
@@ -189,6 +205,7 @@ export function StepInfo({
|
|||||||
<TextField.Icon icon={Lock} />
|
<TextField.Icon icon={Lock} />
|
||||||
<TextField.Input
|
<TextField.Input
|
||||||
testID="passwordInput"
|
testID="passwordInput"
|
||||||
|
inputRef={passwordInputRef}
|
||||||
onChangeText={value => {
|
onChangeText={value => {
|
||||||
passwordValueRef.current = value
|
passwordValueRef.current = value
|
||||||
}}
|
}}
|
||||||
@@ -197,6 +214,11 @@ export function StepInfo({
|
|||||||
secureTextEntry
|
secureTextEntry
|
||||||
autoComplete="new-password"
|
autoComplete="new-password"
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
|
returnKeyType="next"
|
||||||
|
submitBehavior={native('blurAndSubmit')}
|
||||||
|
onSubmitEditing={native(() =>
|
||||||
|
birthdateInputRef.current?.focus(),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
</View>
|
</View>
|
||||||
@@ -206,6 +228,7 @@ export function StepInfo({
|
|||||||
</DateField.LabelText>
|
</DateField.LabelText>
|
||||||
<DateField.DateField
|
<DateField.DateField
|
||||||
testID="date"
|
testID="date"
|
||||||
|
inputRef={birthdateInputRef}
|
||||||
value={state.dateOfBirth}
|
value={state.dateOfBirth}
|
||||||
onChangeDate={date => {
|
onChangeDate={date => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|||||||
Reference in New Issue
Block a user