120 lines
2.6 KiB
TypeScript
120 lines
2.6 KiB
TypeScript
|
/**
|
||
|
* External dependencies
|
||
|
*/
|
||
|
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,
|
||
|
};
|
||
|
|
||
|
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 );
|
||
|
|
||
|
const getInitialConfigValues = () =>
|
||
|
fields.reduce(
|
||
|
( data, field ) => ( {
|
||
|
...data,
|
||
|
[ field.id ]:
|
||
|
field.type === 'checkbox'
|
||
|
? field.value === 'yes'
|
||
|
: field.value,
|
||
|
} ),
|
||
|
{}
|
||
|
);
|
||
|
|
||
|
return (
|
||
|
<Form
|
||
|
initialValues={ getInitialConfigValues() }
|
||
|
onChangeCallback={ onChange }
|
||
|
onSubmitCallback={ onSubmit }
|
||
|
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>
|
||
|
);
|
||
|
};
|