/**
* WordPress dependencies
*/
import { useContext, useMemo } from '@wordpress/element';
import { Stack } from '@wordpress/ui';
/**
* Internal dependencies
*/
import type {
FieldValidity,
FormValidity,
NormalizedForm,
NormalizedFormField,
} from '../../types';
import { getFormFieldLayout } from './index';
import DataFormContext from '../dataform-context';
const DEFAULT_WRAPPER = ( { children }: { children: React.ReactNode } ) => (
{ children }
);
export function DataFormLayout< Item >( {
data,
form,
onChange,
validity,
children,
as,
}: {
data: Item;
form: NormalizedForm;
onChange: ( value: any ) => void;
validity?: FormValidity;
children?: (
FieldLayout: ( props: {
data: Item;
field: NormalizedFormField;
onChange: ( value: any ) => void;
hideLabelFromVision?: boolean;
markWhenOptional?: boolean;
validity?: FieldValidity;
} ) => React.JSX.Element | null,
childField: NormalizedFormField,
childFieldValidity?: FieldValidity,
markWhenOptional?: boolean
) => React.JSX.Element;
as?: React.ComponentType< { children: React.ReactNode } >;
} ) {
const { fields: fieldDefinitions } = useContext( DataFormContext );
// Auto-compute: mark the minority of fields
// When counts are equal, mark required fields
const markWhenOptional = useMemo( () => {
const requiredCount = fieldDefinitions.filter(
( f ) => !! f.isValid?.required
).length;
const optionalCount = fieldDefinitions.length - requiredCount;
return requiredCount > optionalCount;
}, [ fieldDefinitions ] );
function getFieldDefinition( field: NormalizedFormField ) {
return fieldDefinitions.find(
( fieldDefinition ) => fieldDefinition.id === field.id
);
}
const Wrapper =
as ??
getFormFieldLayout( form.layout.type )?.wrapper ??
DEFAULT_WRAPPER;
return (
{ form.fields.map( ( formField ) => {
const FieldLayout = getFormFieldLayout( formField.layout.type )
?.component;
if ( ! FieldLayout ) {
return null;
}
const fieldDefinition = ! formField.children
? getFieldDefinition( formField )
: undefined;
if (
fieldDefinition &&
fieldDefinition.isVisible &&
! fieldDefinition.isVisible( data )
) {
return null;
}
if ( children ) {
return children(
FieldLayout,
formField,
validity?.[ formField.id ],
markWhenOptional
);
}
return (
);
} ) }
);
}