You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Input.tsx 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import React, { forwardRef, useCallback, useState } from 'react';
  2. import {
  3. KeyboardTypeOptions,
  4. NativeSyntheticEvent,
  5. ReturnKeyTypeOptions,
  6. StyleProp,
  7. Text,
  8. TextInput,
  9. TextInputChangeEventData,
  10. TextInputFocusEventData,
  11. TextInputKeyPressEventData,
  12. TextInputSubmitEditingEventData,
  13. TextStyle,
  14. TouchableOpacity,
  15. View,
  16. ViewStyle
  17. } from 'react-native';
  18. import Icon from '../../../icons/components/Icon';
  19. import { IconCloseCircle } from '../../../icons/svg';
  20. import BaseTheme from '../../../ui/components/BaseTheme.native';
  21. import { IInputProps } from '../types';
  22. import styles from './inputStyles';
  23. interface IProps extends IInputProps {
  24. accessibilityLabel?: any;
  25. autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters' | undefined;
  26. autoFocus?: boolean;
  27. blurOnSubmit?: boolean | undefined;
  28. bottomLabel?: string;
  29. customStyles?: ICustomStyles;
  30. editable?: boolean | undefined;
  31. /**
  32. * The id to set on the input element.
  33. * This is required because we need it internally to tie the input to its
  34. * info (label, error) so that screen reader users don't get lost.
  35. */
  36. id?: string;
  37. keyboardType?: KeyboardTypeOptions;
  38. maxLength?: number | undefined;
  39. minHeight?: number | string | undefined;
  40. multiline?: boolean | undefined;
  41. numberOfLines?: number | undefined;
  42. onBlur?: ((e: NativeSyntheticEvent<TextInputFocusEventData>) => void) | undefined;
  43. onFocus?: ((e: NativeSyntheticEvent<TextInputFocusEventData>) => void) | undefined;
  44. onKeyPress?: ((e: NativeSyntheticEvent<TextInputKeyPressEventData>) => void) | undefined;
  45. onSubmitEditing?: (value: string) => void;
  46. pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto' | undefined;
  47. returnKeyType?: ReturnKeyTypeOptions | undefined;
  48. secureTextEntry?: boolean | undefined;
  49. textContentType?: any;
  50. }
  51. interface ICustomStyles {
  52. container?: Object;
  53. input?: Object;
  54. }
  55. const Input = forwardRef<TextInput, IProps>(({
  56. accessibilityLabel,
  57. autoCapitalize,
  58. autoFocus,
  59. blurOnSubmit,
  60. bottomLabel,
  61. clearable,
  62. customStyles,
  63. disabled,
  64. error,
  65. icon,
  66. id,
  67. keyboardType,
  68. label,
  69. maxLength,
  70. minHeight,
  71. multiline,
  72. numberOfLines,
  73. onBlur,
  74. onChange,
  75. onFocus,
  76. onKeyPress,
  77. onSubmitEditing,
  78. placeholder,
  79. pointerEvents,
  80. returnKeyType,
  81. secureTextEntry,
  82. textContentType,
  83. value
  84. }: IProps, ref) => {
  85. const [ focused, setFocused ] = useState(false);
  86. const handleChange = useCallback((e: NativeSyntheticEvent<TextInputChangeEventData>) => {
  87. const { nativeEvent: { text } } = e;
  88. onChange?.(text);
  89. }, [ onChange ]);
  90. const clearInput = useCallback(() => {
  91. onChange?.('');
  92. }, [ onChange ]);
  93. const handleBlur = useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
  94. setFocused(false);
  95. onBlur?.(e);
  96. }, [ onBlur ]);
  97. const handleFocus = useCallback((e: NativeSyntheticEvent<TextInputFocusEventData>) => {
  98. setFocused(true);
  99. onFocus?.(e);
  100. }, [ onFocus ]);
  101. const handleKeyPress = useCallback((e: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
  102. onKeyPress?.(e);
  103. }, [ onKeyPress ]);
  104. const handleSubmitEditing = useCallback((e: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => {
  105. const { nativeEvent: { text } } = e;
  106. onSubmitEditing?.(text);
  107. }, [ onSubmitEditing ]);
  108. return (<View style = { [ styles.inputContainer, customStyles?.container ] as StyleProp<ViewStyle> }>
  109. {label && <Text style = { styles.label }>{ label }</Text>}
  110. <View style = { styles.fieldContainer as StyleProp<ViewStyle> }>
  111. {icon && <Icon
  112. size = { 22 }
  113. src = { icon }
  114. style = { styles.icon } />}
  115. <TextInput
  116. accessibilityLabel = { accessibilityLabel }
  117. autoCapitalize = { autoCapitalize }
  118. autoComplete = { 'off' }
  119. autoCorrect = { false }
  120. autoFocus = { autoFocus }
  121. blurOnSubmit = { blurOnSubmit }
  122. editable = { !disabled }
  123. id = { id }
  124. keyboardType = { keyboardType }
  125. maxLength = { maxLength }
  126. // @ts-ignore
  127. minHeight = { minHeight }
  128. multiline = { multiline }
  129. numberOfLines = { numberOfLines }
  130. onBlur = { handleBlur }
  131. onChange = { handleChange }
  132. onFocus = { handleFocus }
  133. onKeyPress = { handleKeyPress }
  134. onSubmitEditing = { handleSubmitEditing }
  135. placeholder = { placeholder }
  136. placeholderTextColor = { BaseTheme.palette.text02 }
  137. pointerEvents = { pointerEvents }
  138. ref = { ref }
  139. returnKeyType = { returnKeyType }
  140. secureTextEntry = { secureTextEntry }
  141. spellCheck = { false }
  142. style = { [
  143. styles.input,
  144. clearable && styles.clearableInput,
  145. customStyles?.input,
  146. disabled && styles.inputDisabled,
  147. icon && styles.iconInput,
  148. multiline && styles.inputMultiline,
  149. focused && styles.inputFocused,
  150. error && styles.inputError
  151. ] as StyleProp<TextStyle> }
  152. textContentType = { textContentType }
  153. value = { typeof value === 'number' ? `${value}` : value } />
  154. { clearable && !disabled && value !== '' && (
  155. <TouchableOpacity
  156. onPress = { clearInput }
  157. style = { styles.clearButton as StyleProp<ViewStyle> }>
  158. <Icon
  159. size = { 22 }
  160. src = { IconCloseCircle }
  161. style = { styles.clearIcon } />
  162. </TouchableOpacity>
  163. )}
  164. </View>
  165. {
  166. bottomLabel && (
  167. <View>
  168. <Text
  169. id = { `${id}-description` }
  170. style = { [
  171. styles.bottomLabel,
  172. error && styles.bottomLabelError
  173. ] }>
  174. { bottomLabel }
  175. </Text>
  176. </View>
  177. )
  178. }
  179. </View>);
  180. });
  181. export default Input;