diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 95f6437e77..87d0a08372 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -3,12 +3,14 @@ import {View, Dimensions} from 'react-native' import BottomSheet, { BottomSheetBackdrop, BottomSheetScrollView, + BottomSheetTextInput, BottomSheetView, } from '@gorhom/bottom-sheet' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useTheme, atoms as a} from '#/alf' import {Portal} from '#/components/Portal' +import {createTextInput} from '#/components/forms/InputText' import { DialogOuterProps, @@ -19,6 +21,8 @@ import {Context} from '#/components/Dialog/context' export {useDialogControl, useDialogContext} from '#/components/Dialog/context' export * from '#/components/Dialog/types' +// @ts-ignore +export const InputText = createTextInput(BottomSheetTextInput) export function Outer({ children, diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx index 514013d673..6ddc1b0b4a 100644 --- a/src/components/Dialog/index.web.tsx +++ b/src/components/Dialog/index.web.tsx @@ -13,6 +13,7 @@ import {Context, useDialogContext} from '#/components/Dialog/context' export {useDialogControl, useDialogContext} from '#/components/Dialog/context' export * from '#/components/Dialog/types' +export {InputText} from '#/components/forms/InputText' const stopPropagation = (e: any) => e.stopPropagation() diff --git a/src/components/forms/InputText.tsx b/src/components/forms/InputText.tsx index 9c91ccf2aa..5a6b60d468 100644 --- a/src/components/forms/InputText.tsx +++ b/src/components/forms/InputText.tsx @@ -20,221 +20,229 @@ type Props = BaseProps & suffix?: React.FunctionComponent } -export function InputText({ - value: initialValue, - onChange, - testID, - accessibilityLabel, - accessibilityHint, - label, - hasError, - icon: Icon, - suffix: Suffix, - ...props -}: Props) { - const labelId = React.useId() - const t = useTheme() - const [value, setValue] = React.useState(initialValue) - const [suffixPadding, setSuffixPadding] = React.useState(0) - const { - state: hovered, - onIn: onHoverIn, - onOut: onHoverOut, - } = useInteractionState() - const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() - const hasIcon = !!Icon +export function createTextInput(Input: typeof TextInput) { + return function InputText({ + value: initialValue, + onChange, + testID, + accessibilityLabel, + accessibilityHint, + label, + hasError, + icon: Icon, + suffix: Suffix, + ...props + }: Props) { + const labelId = React.useId() + const t = useTheme() + const [value, setValue] = React.useState(initialValue) + const [suffixPadding, setSuffixPadding] = React.useState(0) + const { + state: hovered, + onIn: onHoverIn, + onOut: onHoverOut, + } = useInteractionState() + const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() + const hasIcon = !!Icon - const handleSuffixLayout = React.useCallback( - (e: LayoutChangeEvent) => { - setSuffixPadding(e.nativeEvent.layout.width + 16) - }, - [setSuffixPadding], - ) + const handleSuffixLayout = React.useCallback( + (e: LayoutChangeEvent) => { + setSuffixPadding(e.nativeEvent.layout.width + 16) + }, + [setSuffixPadding], + ) - const {inputBaseStyles, inputHoverStyles, inputFocusStyles} = - React.useMemo(() => { - const base: TextStyle[] = [] - const hover: TextStyle[] = [ - { - borderColor: t.palette.contrast_300, - }, - ] - const focus: TextStyle[] = [ - { - backgroundColor: t.palette.contrast_50, - borderColor: t.palette.primary_500, - }, - ] + const {inputBaseStyles, inputHoverStyles, inputFocusStyles} = + React.useMemo(() => { + const base: TextStyle[] = [] + const hover: TextStyle[] = [ + { + borderColor: t.palette.contrast_300, + }, + ] + const focus: TextStyle[] = [ + { + backgroundColor: t.palette.contrast_50, + borderColor: t.palette.primary_500, + }, + ] - if (hasIcon) { - base.push({ - paddingLeft: 40, - }) - } + if (hasIcon) { + base.push({ + paddingLeft: 40, + }) + } - if (hasError) { - base.push({ - backgroundColor: - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, - borderColor: - t.name === 'light' - ? t.palette.negative_300 - : t.palette.negative_800, - }) - hover.push({ - borderColor: tokens.color.red_500, - }) - focus.push({ - backgroundColor: - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, - borderColor: tokens.color.red_500, - }) - } + if (hasError) { + base.push({ + backgroundColor: + t.name === 'light' + ? t.palette.negative_25 + : t.palette.negative_900, + borderColor: + t.name === 'light' + ? t.palette.negative_300 + : t.palette.negative_800, + }) + hover.push({ + borderColor: tokens.color.red_500, + }) + focus.push({ + backgroundColor: + t.name === 'light' + ? t.palette.negative_25 + : t.palette.negative_900, + borderColor: tokens.color.red_500, + }) + } - return { - inputBaseStyles: base, - inputHoverStyles: hover, - inputFocusStyles: focus, - } - }, [t, hasError, hasIcon]) + return { + inputBaseStyles: base, + inputHoverStyles: hover, + inputFocusStyles: focus, + } + }, [t, hasError, hasIcon]) - const {iconBaseStyles, iconHoverStyles, iconFocusStyles} = - React.useMemo(() => { - const base: TextStyle[] = [] - const hover: TextStyle[] = [ - { - color: t.palette.contrast_500, - }, - ] - const focus: TextStyle[] = [ - { - color: t.palette.primary_500, - }, - ] + const {iconBaseStyles, iconHoverStyles, iconFocusStyles} = + React.useMemo(() => { + const base: TextStyle[] = [] + const hover: TextStyle[] = [ + { + color: t.palette.contrast_500, + }, + ] + const focus: TextStyle[] = [ + { + color: t.palette.primary_500, + }, + ] - if (hasError) { - base.push({ - color: t.palette.negative_400, - }) - hover.push({ - color: t.palette.negative_500, - }) - focus.push({ - color: t.palette.negative_500, - }) - } + if (hasError) { + base.push({ + color: t.palette.negative_400, + }) + hover.push({ + color: t.palette.negative_500, + }) + focus.push({ + color: t.palette.negative_500, + }) + } - return { - iconBaseStyles: base, - iconHoverStyles: hover, - iconFocusStyles: focus, - } - }, [t, hasError]) + return { + iconBaseStyles: base, + iconHoverStyles: hover, + iconFocusStyles: focus, + } + }, [t, hasError]) - const handleOnChange = React.useCallback( - (e: any) => { - const value = e.currentTarget.value - onChange(value) - setValue(value) - }, - [onChange, setValue], - ) + const handleOnChange = React.useCallback( + (e: any) => { + const value = e.currentTarget.value + onChange(value) + setValue(value) + }, + [onChange, setValue], + ) - return ( - - {label && ( - - {label} - - )} - - - - {Icon && ( - - + {label && ( + - - )} + atoms.text_sm, + atoms.font_bold, + t.atoms.text_contrast_600, + atoms.mb_sm, + ]}> + {label} + + )} - {Suffix && ( - - - - )} - - ) + t.atoms.bg_contrast_50, + atoms.w_full, + atoms.px_lg, + atoms.py_md, + atoms.rounded_sm, + atoms.text_md, + t.atoms.text, + web({ + paddingTop: atoms.pt_md.paddingTop - 1, + }), + {borderColor: 'transparent', paddingRight: suffixPadding}, + {borderWidth: 2, lineHeight: atoms.text_md.lineHeight * 1.1875}, + ...inputBaseStyles, + ...(hovered ? inputHoverStyles : []), + ...(focused ? inputFocusStyles : []), + ...(Array.isArray(props.style) ? props.style : [props.style]), + ]} + /> + + {Icon && ( + + + + )} + + {Suffix && ( + + + + )} + + ) + } } + +export const InputText = createTextInput(TextInput) diff --git a/src/view/screens/Storybook/Dialogs.tsx b/src/view/screens/Storybook/Dialogs.tsx index 9dd76be40a..5ad6764b0d 100644 --- a/src/view/screens/Storybook/Dialogs.tsx +++ b/src/view/screens/Storybook/Dialogs.tsx @@ -56,6 +56,14 @@ export function Dialogs() {

Dialog

Description

+ {}} + placeholder="Type here" + accessibilityLabel="Type" + accessibilityHint="Type" + />