Skip to content

Commit

Permalink
Remove field type checking within dataform layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
louwie17 committed Nov 5, 2024
1 parent 4cd314b commit ddf996a
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 102 deletions.
4 changes: 2 additions & 2 deletions packages/dataviews/src/components/dataform-context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { FormField, NormalizedField } from '../../types';

type DataFormContextType< Item > = {
getFieldDefinition: (
field: FormField
field: FormField | string
) => NormalizedField< Item > | undefined;
};

Expand All @@ -23,7 +23,7 @@ export function DataFormProvider< Item >( {
children,
}: React.PropsWithChildren< { fields: NormalizedField< Item >[] } > ) {
const getFieldDefinition = useCallback(
( field: FormField ) => {
( field: FormField | string ) => {
const fieldId = typeof field === 'string' ? field : field.id;

const definition = fields.find(
Expand Down
110 changes: 62 additions & 48 deletions packages/dataviews/src/components/dataform/stories/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ToggleControl } from '@wordpress/components';
* Internal dependencies
*/
import DataForm from '../index';
import type { Field, Form } from '../../../types';
import type { Field, Form, FormField } from '../../../types';

type SamplePost = {
title: string;
Expand Down Expand Up @@ -123,6 +123,33 @@ const fields = [
},
] as Field< SamplePost >[];

function toFormField(
formFields: Array< string | FormField >,
labelPosition: 'default' | 'top' | 'side',
type: 'panel' | 'regular'
): FormField[] {
return formFields.map( ( field ) => {
if ( typeof field === 'string' ) {
return {
id: field,
layout: type,
labelPosition:
labelPosition === 'default' ? undefined : labelPosition,
};
} else if (
typeof field !== 'string' &&
field.children &&
type !== 'panel'
) {
return {
...field,
children: toFormField( field.children, labelPosition, type ),
};
}
return field;
} );
}

export const Default = ( {
type,
labelPosition,
Expand All @@ -143,32 +170,27 @@ export const Default = ( {

const form = useMemo(
() => ( {
fields: [
'title',
'order',
{
id: 'sticky',
layout: 'regular',
labelPosition: type === 'regular' ? labelPosition : 'side',
},
'author',
'reviewer',
'password',
'date',
'birthdate',
].map( ( field ) => {
if (
labelPosition !== 'default' &&
typeof field === 'string'
) {
return {
id: field,
layout: type,
labelPosition,
};
}
return field;
} ),
fields: toFormField(
[
'title',
'order',
{
id: 'sticky',
layout: 'regular',
labelPosition:
type === 'regular' && labelPosition !== 'default'
? labelPosition
: 'side',
},
'author',
'reviewer',
'password',
'date',
'birthdate',
],
labelPosition,
type
),
} ),
[ type, labelPosition ]
) as Form;
Expand Down Expand Up @@ -210,27 +232,19 @@ const CombinedFieldsComponent = ( {

const form = useMemo(
() => ( {
fields: [
'title',
{
id: 'status',
children: [ 'status', 'password' ],
},
'order',
'author',
].map( ( field ) => {
if (
labelPosition !== 'default' &&
typeof field === 'string'
) {
return {
id: field,
layout: type,
labelPosition,
};
}
return field;
} ),
fields: toFormField(
[
'title',
{
id: 'status',
children: [ 'status', 'password' ],
},
'order',
'author',
],
labelPosition,
type
),
} ),
[ type, labelPosition ]
) as Form;
Expand Down
24 changes: 14 additions & 10 deletions packages/dataviews/src/dataforms-layouts/data-form-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function DataFormLayout< Item >( {
}: {
defaultLayout?: string;
data: Item;
fields: FormField[];
fields: Array< FormField | string >;
onChange: ( value: any ) => void;
children?: (
FieldLayout: ( props: {
Expand All @@ -37,10 +37,15 @@ export function DataFormLayout< Item >( {
return (
<VStack spacing={ 2 }>
{ fields.map( ( field ) => {
const fieldLayoutId =
typeof field !== 'string' && field.layout
? field.layout
: defaultLayout;
const formField: FormField =
typeof field !== 'string'
? field
: {
id: field,
};
const fieldLayoutId = formField.layout
? formField.layout
: defaultLayout;
const FieldLayout = getFormFieldLayout(
fieldLayoutId ?? 'regular'
)?.component;
Expand All @@ -49,8 +54,7 @@ export function DataFormLayout< Item >( {
return null;
}

const fieldId = typeof field === 'string' ? field : field.id;
const fieldDefinition = getFieldDefinition( fieldId );
const fieldDefinition = getFieldDefinition( formField );

if (
! fieldDefinition ||
Expand All @@ -61,14 +65,14 @@ export function DataFormLayout< Item >( {
}

if ( children ) {
return children( FieldLayout, field );
return children( FieldLayout, formField );
}

return (
<FieldLayout
key={ fieldId }
key={ formField.id }
data={ data }
field={ field }
field={ formField }
onChange={ onChange }
/>
);
Expand Down
16 changes: 0 additions & 16 deletions packages/dataviews/src/dataforms-layouts/get-visible-fields.ts

This file was deleted.

23 changes: 12 additions & 11 deletions packages/dataviews/src/dataforms-layouts/panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,18 @@ function PanelDropdown< Item >( {
popoverAnchor: HTMLElement | null;
} & FormFieldProps< Item > ) {
const childrenFields = useMemo( () => {
const isFieldObject = typeof field !== 'string';
if ( isFieldObject && field.children ) {
return field.children;
if ( field.children ) {
return field.children.map( ( child ) => {
if ( typeof child === 'string' ) {
return {
id: child,
};
}
return child;
} );
}
if ( isFieldObject && field.id ) {
return [ field.id ];
}
return [ field ];
// If not explicit children return the field id itself.
return [ { id: field.id } ];
}, [ field ] );

// Memoize popoverProps to avoid returning a new object every time.
Expand Down Expand Up @@ -159,10 +163,7 @@ export default function FormPanelField< Item >( {
}: FormFieldProps< Item > ) {
const { getFieldDefinition } = useContext( DataFormContext );
const fieldDefinition = getFieldDefinition( field );
const labelPosition =
typeof field !== 'string' && field.labelPosition
? field.labelPosition
: 'side';
const labelPosition = field.labelPosition ?? 'side';

// Use internal state instead of a ref to make sure that the component
// re-renders when the popover's anchor updates.
Expand Down
14 changes: 9 additions & 5 deletions packages/dataviews/src/dataforms-layouts/regular/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ export default function FormRegularField< Item >( {
}: FormFieldProps< Item > ) {
const { getFieldDefinition } = useContext( DataFormContext );
const fieldDefinition = getFieldDefinition( field );
const labelPosition =
typeof field !== 'string' && field.labelPosition
? field.labelPosition
: 'top';
const labelPosition = field.labelPosition ?? 'top';
const childrenFields = useMemo( () => {
if ( typeof field !== 'string' && field.children ) {
return field.children;
return field.children.map( ( child ) => {
if ( typeof child === 'string' ) {
return {
id: child,
};
}
return child;
} );
}
return [];
}, [ field ] );
Expand Down
18 changes: 8 additions & 10 deletions packages/dataviews/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,22 +525,20 @@ export interface SupportedLayouts {
table?: Omit< ViewTable, 'type' >;
}

export type FormField =
| string
| {
id: string;
label?: string;
layout?: 'regular' | 'panel';
labelPosition?: 'side' | 'top';
children?: FormField[];
};
export type FormField = {
id: string;
label?: string;
layout?: 'regular' | 'panel';
labelPosition?: 'side' | 'top';
children?: Array< FormField | string >;
};

/**
* The form configuration.
*/
export type Form = {
type?: 'regular' | 'panel';
fields?: FormField[];
fields?: Array< FormField | string >;
};

export interface DataFormProps< Item > {
Expand Down

0 comments on commit ddf996a

Please sign in to comment.