Improve types for InputText, value handling
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
import {TextInputProps} from 'react-native'
|
||||||
|
|
||||||
|
import {BaseProps} from '#/view/com/forms/types'
|
||||||
|
|
||||||
|
export type InputDateProps = BaseProps & {
|
||||||
|
/**
|
||||||
|
* **NOTE:** Available only on web
|
||||||
|
*/
|
||||||
|
autoFocus?: TextInputProps['autoFocus']
|
||||||
|
}
|
||||||
@@ -9,16 +9,23 @@ import {
|
|||||||
|
|
||||||
import {useTheme, atoms, web, tokens} from '#/alf'
|
import {useTheme, atoms, web, tokens} from '#/alf'
|
||||||
import {Text} from '#/view/com/Typography'
|
import {Text} from '#/view/com/Typography'
|
||||||
|
import {useInteractionState} from '#/view/com/util/hooks/useInteractionState'
|
||||||
|
|
||||||
type Props = Omit<TextInputProps, 'placeholder'> & {
|
import {BaseProps} from '#/view/com/forms/types'
|
||||||
label?: string
|
|
||||||
placeholder: string
|
type Props = BaseProps &
|
||||||
hasError?: boolean
|
Omit<TextInputProps, 'placeholder'> & {
|
||||||
icon?: React.FunctionComponent<any>
|
placeholder: Required<TextInputProps>['placeholder']
|
||||||
suffix?: React.FunctionComponent<any>
|
icon?: React.FunctionComponent<any>
|
||||||
}
|
suffix?: React.FunctionComponent<any>
|
||||||
|
}
|
||||||
|
|
||||||
export function InputText({
|
export function InputText({
|
||||||
|
value: initialValue,
|
||||||
|
onChange,
|
||||||
|
testID,
|
||||||
|
accessibilityLabel,
|
||||||
|
accessibilityHint,
|
||||||
label,
|
label,
|
||||||
hasError,
|
hasError,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
@@ -27,36 +34,15 @@ export function InputText({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
const labelId = React.useId()
|
const labelId = React.useId()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const [state, setState] = React.useState({
|
const [value, setValue] = React.useState<string>(initialValue)
|
||||||
hovered: false,
|
|
||||||
focused: false,
|
|
||||||
})
|
|
||||||
const [suffixPadding, setSuffixPadding] = React.useState(0)
|
const [suffixPadding, setSuffixPadding] = React.useState(0)
|
||||||
|
const {
|
||||||
|
state: hovered,
|
||||||
|
onIn: onHoverIn,
|
||||||
|
onOut: onHoverOut,
|
||||||
|
} = useInteractionState()
|
||||||
|
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
|
||||||
|
|
||||||
const onHoverIn = React.useCallback(() => {
|
|
||||||
setState(s => ({
|
|
||||||
...s,
|
|
||||||
hovered: true,
|
|
||||||
}))
|
|
||||||
}, [setState])
|
|
||||||
const onHoverOut = React.useCallback(() => {
|
|
||||||
setState(s => ({
|
|
||||||
...s,
|
|
||||||
hovered: false,
|
|
||||||
}))
|
|
||||||
}, [setState])
|
|
||||||
const onFocus = React.useCallback(() => {
|
|
||||||
setState(s => ({
|
|
||||||
...s,
|
|
||||||
focused: true,
|
|
||||||
}))
|
|
||||||
}, [setState])
|
|
||||||
const onBlur = React.useCallback(() => {
|
|
||||||
setState(s => ({
|
|
||||||
...s,
|
|
||||||
focused: false,
|
|
||||||
}))
|
|
||||||
}, [setState])
|
|
||||||
const handleSuffixLayout = React.useCallback(
|
const handleSuffixLayout = React.useCallback(
|
||||||
(e: LayoutChangeEvent) => {
|
(e: LayoutChangeEvent) => {
|
||||||
setSuffixPadding(e.nativeEvent.layout.width + 16)
|
setSuffixPadding(e.nativeEvent.layout.width + 16)
|
||||||
@@ -83,7 +69,7 @@ export function InputText({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.hovered || state.focused) {
|
if (hovered || focused) {
|
||||||
input.push({
|
input.push({
|
||||||
borderColor: t.atoms.border_contrast_500.borderColor,
|
borderColor: t.atoms.border_contrast_500.borderColor,
|
||||||
})
|
})
|
||||||
@@ -96,7 +82,16 @@ export function InputText({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {inputStyles: input, iconStyles: icon}
|
return {inputStyles: input, iconStyles: icon}
|
||||||
}, [t, state, hasError, Icon])
|
}, [t, hovered, focused, hasError, Icon])
|
||||||
|
|
||||||
|
const handleOnChange = React.useCallback(
|
||||||
|
(e: any) => {
|
||||||
|
const value = e.currentTarget.value
|
||||||
|
onChange(value)
|
||||||
|
setValue(value)
|
||||||
|
},
|
||||||
|
[onChange, setValue],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[atoms.relative, atoms.w_full]}>
|
<View style={[atoms.relative, atoms.w_full]}>
|
||||||
@@ -114,12 +109,17 @@ export function InputText({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
|
{...props}
|
||||||
|
value={value}
|
||||||
|
testID={testID}
|
||||||
aria-labelledby={labelId}
|
aria-labelledby={labelId}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
|
accessibilityLabel={accessibilityLabel}
|
||||||
|
accessibilityHint={accessibilityHint}
|
||||||
placeholderTextColor={t.atoms.text_contrast_500.color}
|
placeholderTextColor={t.atoms.text_contrast_500.color}
|
||||||
{...props}
|
|
||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
|
onChange={handleOnChange}
|
||||||
{...web({
|
{...web({
|
||||||
onMouseEnter: onHoverIn,
|
onMouseEnter: onHoverIn,
|
||||||
onMouseLeave: onHoverOut,
|
onMouseLeave: onHoverOut,
|
||||||
|
|||||||
@@ -218,12 +218,39 @@ export function Buttons() {
|
|||||||
function Forms() {
|
function Forms() {
|
||||||
return (
|
return (
|
||||||
<View style={[a.gap_md, a.align_start]}>
|
<View style={[a.gap_md, a.align_start]}>
|
||||||
<InputText label="Name" placeholder="Type here" />
|
|
||||||
<InputText placeholder="Type here" icon={Logo} />
|
|
||||||
<InputText hasError placeholder="Type here" icon={Logo} />
|
|
||||||
|
|
||||||
<InputText
|
<InputText
|
||||||
|
testID="input"
|
||||||
|
accessibilityLabel="Input"
|
||||||
|
accessibilityHint="Enter some text"
|
||||||
placeholder="Type here"
|
placeholder="Type here"
|
||||||
|
value=""
|
||||||
|
onChange={text => console.log(text)}
|
||||||
|
/>
|
||||||
|
<InputText
|
||||||
|
hasError
|
||||||
|
testID="input"
|
||||||
|
accessibilityLabel="Input"
|
||||||
|
accessibilityHint="Enter some text"
|
||||||
|
placeholder="Type here"
|
||||||
|
value="Test initial value"
|
||||||
|
onChange={text => console.log(text)}
|
||||||
|
/>
|
||||||
|
<InputText
|
||||||
|
testID="input"
|
||||||
|
accessibilityLabel="Input"
|
||||||
|
accessibilityHint="Enter some text"
|
||||||
|
placeholder="Type here"
|
||||||
|
value=""
|
||||||
|
onChange={text => console.log(text)}
|
||||||
|
icon={Logo}
|
||||||
|
/>
|
||||||
|
<InputText
|
||||||
|
testID="input"
|
||||||
|
accessibilityLabel="Input"
|
||||||
|
accessibilityHint="Enter some text"
|
||||||
|
placeholder="Type here"
|
||||||
|
value=""
|
||||||
|
onChange={text => console.log(text)}
|
||||||
icon={Logo}
|
icon={Logo}
|
||||||
suffix={() => <Text>.bksy.social</Text>}
|
suffix={() => <Text>.bksy.social</Text>}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user