2021-05-18 19:46:21 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2021-06-29 20:06:31 +00:00
|
|
|
import { useMemo } from '@wordpress/element';
|
2021-05-18 19:46:21 +00:00
|
|
|
import { Button } from '@wordpress/components';
|
|
|
|
import { __ } from '@wordpress/i18n';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import { Form } from '../index';
|
|
|
|
import {
|
|
|
|
TextField,
|
|
|
|
PasswordField,
|
|
|
|
CheckboxField,
|
|
|
|
SelectField,
|
|
|
|
} from './field-types';
|
|
|
|
|
|
|
|
import { Field, FormInputProps } from './types';
|
|
|
|
|
|
|
|
type DynamicFormProps = {
|
|
|
|
fields: Field[] | { [ key: string ]: Field };
|
|
|
|
validate: ( values: Record< string, string > ) => Record< string, string >;
|
|
|
|
isBusy?: boolean;
|
|
|
|
onSubmit?: ( values: Record< string, string > ) => void;
|
|
|
|
onChange?: (
|
|
|
|
value: Record< string, string >,
|
|
|
|
values: Record< string, string >[],
|
|
|
|
result: boolean
|
|
|
|
) => void;
|
|
|
|
submitLabel?: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
const fieldTypeMap = {
|
|
|
|
text: TextField,
|
|
|
|
password: PasswordField,
|
|
|
|
checkbox: CheckboxField,
|
|
|
|
select: SelectField,
|
|
|
|
default: TextField,
|
|
|
|
};
|
|
|
|
|
2021-06-29 20:06:31 +00:00
|
|
|
const getInitialConfigValues = ( fields: Field[] ) =>
|
|
|
|
fields.reduce(
|
|
|
|
( data, field ) => ( {
|
|
|
|
...data,
|
|
|
|
[ field.id ]:
|
|
|
|
field.type === 'checkbox' ? field.value === 'yes' : field.value,
|
|
|
|
} ),
|
|
|
|
{}
|
|
|
|
);
|
|
|
|
|
2021-05-18 19:46:21 +00:00
|
|
|
export const DynamicForm: React.FC< DynamicFormProps > = ( {
|
|
|
|
fields: baseFields = [],
|
|
|
|
isBusy = false,
|
|
|
|
onSubmit = () => {},
|
|
|
|
onChange = () => {},
|
|
|
|
validate = () => ( {} ),
|
|
|
|
submitLabel = __( 'Proceed', 'woocommerce-admin' ),
|
|
|
|
} ) => {
|
|
|
|
// Support accepting fields in the format provided by the API (object), but transform to Array
|
|
|
|
const fields =
|
|
|
|
baseFields instanceof Array ? baseFields : Object.values( baseFields );
|
|
|
|
|
2021-06-29 20:06:31 +00:00
|
|
|
const initialValues = useMemo( () => getInitialConfigValues( fields ), [
|
|
|
|
fields,
|
|
|
|
] );
|
2021-05-18 19:46:21 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Form
|
2021-06-29 20:06:31 +00:00
|
|
|
initialValues={ initialValues }
|
2021-05-26 18:31:30 +00:00
|
|
|
onChange={ onChange }
|
|
|
|
onSubmit={ onSubmit }
|
2021-05-18 19:46:21 +00:00
|
|
|
validate={ validate }
|
|
|
|
>
|
|
|
|
{ ( {
|
|
|
|
getInputProps,
|
|
|
|
handleSubmit,
|
|
|
|
}: {
|
|
|
|
getInputProps: ( name: string ) => FormInputProps;
|
|
|
|
handleSubmit: () => void;
|
|
|
|
} ) => {
|
|
|
|
return (
|
|
|
|
<div className="woocommerce-component_dynamic-form">
|
|
|
|
{ fields.map( ( field ) => {
|
|
|
|
if (
|
|
|
|
field.type &&
|
|
|
|
! ( field.type in fieldTypeMap )
|
|
|
|
) {
|
|
|
|
/* eslint-disable no-console */
|
|
|
|
console.warn(
|
|
|
|
`Field type of ${ field.type } not current supported in DynamicForm component`
|
|
|
|
);
|
|
|
|
/* eslint-enable no-console */
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Control =
|
|
|
|
fieldTypeMap[ field.type || 'default' ];
|
|
|
|
return (
|
|
|
|
<Control
|
|
|
|
key={ field.id }
|
|
|
|
field={ field }
|
|
|
|
{ ...getInputProps( field.id ) }
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
} ) }
|
|
|
|
|
|
|
|
<Button
|
|
|
|
isPrimary
|
|
|
|
isBusy={ isBusy }
|
|
|
|
onClick={ () => {
|
|
|
|
handleSubmit();
|
|
|
|
} }
|
|
|
|
>
|
|
|
|
{ submitLabel }
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} }
|
|
|
|
</Form>
|
|
|
|
);
|
|
|
|
};
|