Skip to content

Commit

Permalink
Merge pull request #49700 from software-mansion-labs/289Adam289/49456…
Browse files Browse the repository at this point in the history
…-fix-scroll-bar-and-withOnyx-migration

fix scroll bar on IOS
  • Loading branch information
chiragsalian authored Sep 27, 2024
2 parents 244d751 + 4ed4b90 commit f96baa4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 56 deletions.
79 changes: 26 additions & 53 deletions src/components/Form/FormProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import lodashIsEqual from 'lodash/isEqual';
import type {ForwardedRef, MutableRefObject, ReactNode, RefAttributes} from 'react';
import React, {createRef, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import type {NativeSyntheticEvent, StyleProp, TextInputSubmitEditingEventData, ViewStyle} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
import * as ValidationUtils from '@libs/ValidationUtils';
import Visibility from '@libs/Visibility';
import * as FormActions from '@userActions/FormActions';
import CONST from '@src/CONST';
import type {OnyxFormKey} from '@src/ONYXKEYS';
import type {OnyxFormDraftKey, OnyxFormKey} from '@src/ONYXKEYS';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Form} from '@src/types/form';
import type {Network} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {RegisterInput} from './FormContext';
import FormContext from './FormContext';
Expand Down Expand Up @@ -41,46 +39,34 @@ function getInitialValueByType(valueType?: ValueTypeKey): InitialDefaultValue {
}
}

type FormProviderOnyxProps = {
/** Contains the form state that must be accessed outside the component */
formState: OnyxEntry<Form>;
type FormProviderProps<TFormID extends OnyxFormKey = OnyxFormKey> = FormProps<TFormID> & {
/** Children to render. */
children: ((props: {inputValues: FormOnyxValues<TFormID>}) => ReactNode) | ReactNode;

/** Contains draft values for each input in the form */
draftValues: OnyxEntry<Form>;
/** Callback to validate the form */
validate?: (values: FormOnyxValues<TFormID>) => FormInputErrors<TFormID>;

/** Information about the network */
network: OnyxEntry<Network>;
};

type FormProviderProps<TFormID extends OnyxFormKey = OnyxFormKey> = FormProviderOnyxProps &
FormProps<TFormID> & {
/** Children to render. */
children: ((props: {inputValues: FormOnyxValues<TFormID>}) => ReactNode) | ReactNode;

/** Callback to validate the form */
validate?: (values: FormOnyxValues<TFormID>) => FormInputErrors<TFormID>;
/** Should validate function be called when input loose focus */
shouldValidateOnBlur?: boolean;

/** Should validate function be called when input loose focus */
shouldValidateOnBlur?: boolean;
/** Should validate function be called when the value of the input is changed */
shouldValidateOnChange?: boolean;

/** Should validate function be called when the value of the input is changed */
shouldValidateOnChange?: boolean;
/** Whether to remove invisible characters from strings before validation and submission */
shouldTrimValues?: boolean;

/** Whether to remove invisible characters from strings before validation and submission */
shouldTrimValues?: boolean;
/** Styles that will be applied to the submit button only */
submitButtonStyles?: StyleProp<ViewStyle>;

/** Styles that will be applied to the submit button only */
submitButtonStyles?: StyleProp<ViewStyle>;
/** Whether to apply flex to the submit button */
submitFlexEnabled?: boolean;

/** Whether to apply flex to the submit button */
submitFlexEnabled?: boolean;
/** Whether button is disabled */
isSubmitDisabled?: boolean;

/** Whether button is disabled */
isSubmitDisabled?: boolean;

/** Whether HTML is allowed in form inputs */
allowHTML?: boolean;
};
/** Whether HTML is allowed in form inputs */
allowHTML?: boolean;
};

function FormProvider(
{
Expand All @@ -89,17 +75,17 @@ function FormProvider(
shouldValidateOnBlur = true,
shouldValidateOnChange = true,
children,
formState,
network,
enabledWhenOffline = false,
draftValues,
onSubmit,
shouldTrimValues = true,
allowHTML = false,
...rest
}: FormProviderProps,
forwardedRef: ForwardedRef<FormRef>,
) {
const [network] = useOnyx(ONYXKEYS.NETWORK);
const [formState] = useOnyx<OnyxFormKey, Form>(`${formID}`);
const [draftValues] = useOnyx<OnyxFormDraftKey, Form>(`${formID}Draft`);
const {preferredLocale, translate} = useLocalize();
const inputRefs = useRef<InputRefs>({});
const touchedInputs = useRef<Record<string, boolean>>({});
Expand Down Expand Up @@ -404,19 +390,6 @@ function FormProvider(

FormProvider.displayName = 'Form';

export default withOnyx<FormProviderProps, FormProviderOnyxProps>({
network: {
key: ONYXKEYS.NETWORK,
},
// withOnyx typings are not able to handle such generic cases like this one, since it's a generic component we need to cast the keys to any
formState: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any
key: ({formID}) => formID as any,
},
draftValues: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any
key: (props) => `${props.formID}Draft` as any,
},
})(forwardRef(FormProvider)) as <TFormID extends OnyxFormKey>(props: Omit<FormProviderProps<TFormID> & RefAttributes<FormRef>, keyof FormProviderOnyxProps>) => ReactNode;
export default forwardRef(FormProvider) as <TFormID extends OnyxFormKey>(props: FormProviderProps<TFormID> & RefAttributes<FormRef>) => ReactNode;

export type {FormProviderProps};
20 changes: 17 additions & 3 deletions src/stories/Form.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {Meta, StoryFn} from '@storybook/react';
import React, {useState} from 'react';
import type {ComponentType} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import AddressSearch from '@components/AddressSearch';
import CheckboxWithLabel from '@components/CheckboxWithLabel';
import DatePicker from '@components/DatePicker';
Expand All @@ -18,8 +19,10 @@ import * as FormActions from '@userActions/FormActions';
import CONST from '@src/CONST';
import type {OnyxFormValuesMapping} from '@src/ONYXKEYS';
import {defaultStyles} from '@src/styles';
import type {Form} from '@src/types/form';
import type {Network} from '@src/types/onyx';

type FormStory = StoryFn<FormProviderProps>;
type FormStory = StoryFn<FormProviderProps & FormProviderOnyxProps>;

type StorybookFormValues = {
routingNumber?: string;
Expand All @@ -32,6 +35,17 @@ type StorybookFormValues = {
checkbox?: boolean;
};

type FormProviderOnyxProps = {
/** Contains the form state that must be accessed outside the component */
formState: OnyxEntry<Form>;

/** Contains draft values for each input in the form */
draftValues: OnyxEntry<Form>;

/** Information about the network */
network: OnyxEntry<Network>;
};

type StorybookFormErrors = Partial<Record<keyof StorybookFormValues, string>>;

const STORYBOOK_FORM_ID = 'TestForm' as keyof OnyxFormValuesMapping;
Expand All @@ -50,7 +64,7 @@ const story: Meta<typeof FormProvider> = {
},
};

function Template(props: FormProviderProps) {
function Template(props: FormProviderProps & FormProviderOnyxProps) {
// Form consumes data from Onyx, so we initialize Onyx with the necessary data here
NetworkConnection.setOfflineStatus(false);
FormActions.setIsLoading(props.formID, !!props.formState?.isLoading);
Expand Down Expand Up @@ -162,7 +176,7 @@ function Template(props: FormProviderProps) {
/**
* Story to exhibit the native event handlers for TextInput in the Form Component
*/
function WithNativeEventHandler(props: FormProviderProps) {
function WithNativeEventHandler(props: FormProviderProps & FormProviderOnyxProps) {
const [log, setLog] = useState('');

// Form consumes data from Onyx, so we initialize Onyx with the necessary data here
Expand Down

0 comments on commit f96baa4

Please sign in to comment.