Skip to content

Commit

Permalink
fix: form disabled interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
rabelloo committed Mar 22, 2021
1 parent e7e1e5d commit e406e50
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 32 deletions.
4 changes: 2 additions & 2 deletions packages/core/src/components/field/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ export interface FieldProps {
}

export interface FieldState {
disabled: boolean;
disabled?: boolean;
reset: () => void;
touched: boolean;
touched?: boolean;
validity: ValidityState;
}
27 changes: 11 additions & 16 deletions packages/react/src/components/field/field.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { c, classy, FieldProps as BaseProps, FieldState } from '@onfido/castor';
import { useForm } from '@onfido/castor-react';
import React, { SyntheticEvent, useEffect, useState } from 'react';
import React, { SyntheticEvent, useState } from 'react';
import { FieldProvider } from './useField';

export { useField } from './useField';
Expand Down Expand Up @@ -28,40 +27,31 @@ export const Field = ({
className,
...restProps
}: FieldProps): JSX.Element => {
const form = useForm();
const [field, setField] = useState<FieldState>(initial);

useEffect(() => update(form), [form]);

function initial(): FieldState {
const reset = () => setField(initial);
return { ...form, disabled, reset, validity: {} } as FieldState;
return { reset, validity: {} } as FieldState;
}

const update = (state: Partial<FieldState>) =>
setField((field) => ({ ...field, ...state }));

const readInput = (event: SyntheticEvent<HTMLDivElement>) => {
const { disabled, validity } = event.target as HTMLInputElement;
update({ disabled, validity });
};

return (
<FieldProvider value={field}>
<FieldProvider value={{ ...field, disabled }}>
<div
{...restProps}
className={classy(c('field'), className)}
onBlur={(event) => {
update({ touched: true });
readInput(event);
update({ touched: true, ...readInput(event) });
onBlur?.(event);
}}
onChange={(event) => {
readInput(event);
update({ touched: true, ...readInput(event) });
onChange?.(event);
}}
onInvalid={(event) => {
readInput(event);
update(readInput(event));
onInvalid?.(event);
}}
/>
Expand All @@ -70,3 +60,8 @@ export const Field = ({
};

export type FieldProps = BaseProps & JSX.IntrinsicElements['div'];

const readInput = (event: SyntheticEvent<HTMLDivElement>) => {
const { disabled, validity } = event.target as HTMLInputElement;
return { ...(disabled != null && { disabled }), validity };
};
12 changes: 11 additions & 1 deletion packages/react/src/components/field/useField.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { FieldState } from '@onfido/castor';
import { createContext, useContext } from 'react';
import { useForm } from '../form/useForm';

const FieldContext = createContext({} as FieldState);

export const useField = () => useContext(FieldContext);
export const useField = () => {
const form = useForm();
const field = useContext(FieldContext);

return { ...omitNullish(form), ...omitNullish(field) };
};

export const FieldProvider = FieldContext.Provider;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const omitNullish = (obj: Record<string, any>) =>
Object.fromEntries(Object.entries(obj).filter(([, value]) => value != null));
17 changes: 6 additions & 11 deletions packages/react/src/components/form/form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { c, classy, FormProps as BaseProps, m } from '@onfido/castor';
import React, { FormEvent, useEffect, useState } from 'react';
import React, { FormEvent, useState } from 'react';
import { getFormValues } from './getFormValues';
import { FormProvider, FormState } from './useForm';
import { FormProvider } from './useForm';

export { useForm } from './useForm';

Expand All @@ -13,15 +13,10 @@ export const Form = <T extends Values>({
className,
...restProps
}: FormProps<T>) => {
const [form, setForm] = useState({ disabled } as FormState);

useEffect(() => update({ disabled }), [disabled]);

const update = (values: Partial<FormState>) =>
setForm((form) => ({ ...form, ...values }));
const [touched, setTouched] = useState<boolean>();

return (
<FormProvider value={form}>
<FormProvider value={{ disabled, touched }}>
<form
{...restProps}
className={classy(c('form'), m({ disabled }), className)}
Expand All @@ -30,12 +25,12 @@ export const Form = <T extends Values>({
}
onInvalid={(event) => {
event.preventDefault();
update({ touched: true });
setTouched(true);
onInvalid?.(event);
}}
onSubmit={(event) => {
event.preventDefault();
update({ touched: true });
setTouched(true);

if (disabled) return;

Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/components/form/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ export const useForm = () => useContext(FormContext);
export const FormProvider = FormContext.Provider;

export interface FormState {
disabled: boolean;
touched: boolean;
disabled?: boolean;
touched?: boolean;
}

0 comments on commit e406e50

Please sign in to comment.