woocommerce/packages/js/components/src/dynamic-form/dynamic-form.tsx

123 lines
2.7 KiB
TypeScript
Raw Normal View History

/**
* External dependencies
*/
Allow packages to be built in isolation. (https://github.com/woocommerce/woocommerce-admin/pull/7286) * Use yarn instead of npm. In prep for workspaces, since we're locked to npm < 7. See: https://github.com/woocommerce/woocommerce-admin/pull/7126#issue-661287749 * Initial workspace creation. * Add initial tsc build to @woocommerce/number. * Attempt to build experimental package. * Try currency package. * Define all packages as workspaces. * Use tsconfig common to packages. * Fix currency package build. * Build csv-export with tsc. * Try to build customer-effort-score with tsc. * Fix JSX pragma. * Build data package with tsc. * Build date package with tsc. * Build experimental package with tsc. * Try to build explat package with tsc. * Build navigation package with tsc. * Build notices package with tsc. * Build onboarding package with tsc. * Build components package with tsc. * Swap in package JS build into main script. * Fix experimental package build. * Try per-package css build with components. * Try to run components package tests in isolation. Broken on JSX in test files not being transformed. * Move @woocommerce/wc-admin-settings into a package. * Try to fix components package tests. Fails because we aren't setting up the jest/jest-dom globals. * Move JS test code to reusable (private) package. * Enable incremental TS builds. * Use workspaces to run JS tests. * Use new jest configs for update snapshot scripts. * Fix style builds. * Fix package version in components. * Fix client test debug and watch scripts. * Update yarn lock. * Update test-staged behavior. * Try to fix storybook. * Fix storybook. * Update more npm commands to yarn. * Add changelog. * Fix lint errors. * Update packages readme script references. * Clean up unused gitignore match. * Fix another npm command. * Fix JS builds on watch. * Fix start script. * Fix start scripts for packages. * Use tsc to build packages before tests * yarn -> npm. # Conflicts: # package-lock.json # package.json * Fix linter error. * Remove workspace definitions. * Fix missing Fragment import. * Fix package lock. * Fix missing reference. * Only build commonjs module for js-tests helper. * Remove errant dependency from components. * Remove noop scripts. * Fix package JS build before testing. * Revert noisy formatting changes. * Fix precommit and test scripts. * Fix minimum expected recommended extension count. Japan test case breaks this. * Revert babel config changes. * chore(release): publish - @woocommerce/components@7.2.0 - @woocommerce/csv-export@1.4.0 - @woocommerce/currency@3.2.0 - @woocommerce/customer-effort-score@1.1.0 - @woocommerce/data@1.4.0 - @woocommerce/date@3.1.0 - @woocommerce/dependency-extraction-webpack-plugin@1.7.0 - @woocommerce/eslint-plugin@1.3.0 - @woocommerce/experimental@1.5.0 - @woocommerce/explat@1.1.0 - @woocommerce/js-tests@1.1.0 - @woocommerce/navigation@6.1.0 - @woocommerce/notices@3.1.0 - @woocommerce/number@2.2.0 - @woocommerce/onboarding@1.1.0 - @woocommerce/tracks@1.1.0 - @woocommerce/wc-admin-settings@1.1.0 * Add script for running 'start' in a package. * Remove yarn from gitignore. * Update package changelogs, prep versions for release. * Try to fix E2E tests after main merge. * Some cleanup. * Add changelog. Co-authored-by: Paul Sealock <psealock@gmail.com>
2021-07-14 20:38:57 +00:00
import { createElement, useMemo } from '@wordpress/element';
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,
};
const getInitialConfigValues = ( fields: Field[] ) =>
fields.reduce(
( data, field ) => ( {
...data,
[ field.id ]:
field.type === 'checkbox' ? field.value === 'yes' : field.value,
} ),
{}
);
export const DynamicForm: React.FC< DynamicFormProps > = ( {
fields: baseFields = [],
isBusy = false,
onSubmit = () => {},
onChange = () => {},
validate = () => ( {} ),
submitLabel = __( 'Proceed', 'woocommerce' ),
} ) => {
// 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 initialValues = useMemo( () => getInitialConfigValues( fields ), [
fields,
] );
return (
<Form
initialValues={ initialValues }
onChange={ onChange }
onSubmit={ 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>
);
};