import React, { Children, useState, ReactNode } from 'react'; import { KeyboardAvoidingView, Platform, Pressable, Text, StyleSheet, TextInputSubmitEditingEventData, NativeSyntheticEvent, ViewStyle, } from 'react-native'; import { containsError } from '../FormItem'; import { colors } from '../../colors'; interface Props { children: ReactNode; keyboardVerticalOffset?: number; buttonText?: string; buttonStyle?: object | object[]; buttonTextStyle?: object | object[]; onButtonPress?: () => void; style?: ViewStyle; hideSubmitButton?: boolean; } export let submitForm: ( e?: NativeSyntheticEvent ) => void; export default function Form(props: Props) { const [width, setWidth] = useState(0); const [opacity, setOpacity] = useState(1); const handleButtonPress = () => { const fieldsWithError: string[] = []; Children.forEach(props.children, (child, index) => { //@ts-ignore if (child && child.ref?.current?.getComponent() == 'FormItem') { const { keyboardType, isRequired, value, customValidation } = //@ts-ignore child.props; let validation; if (customValidation) validation = customValidation(); if (containsError(keyboardType, isRequired, value, validation).status) { fieldsWithError.push( //@ts-ignore child.props.label || child.props.placeholder || 'FormItem' + index ); //@ts-ignore child.ref?.current.setState(); } } }); if (fieldsWithError.length) { console.error( 'The following fields do not fulfil their conditions:\n' + JSON.stringify(fieldsWithError, null, 2) ); return; } props.onButtonPress?.(); }; submitForm = () => handleButtonPress(); return ( {props.children} {!props.hideSubmitButton && ( setWidth(event.nativeEvent.layout.width)} onPressIn={() => setOpacity(0.5)} onPressOut={() => setOpacity(1)} > {props.buttonText || 'Submit'} )} ); } Form.defaultProps = { style: {}, }; const styles = StyleSheet.create({ button: { height: 48, justifyContent: 'center', alignItems: 'center', backgroundColor: colors.red, borderRadius: 8, marginVertical: 32, }, buttonText: { color: 'white', fontSize: 16, fontWeight: 'bold', }, });